操纵 Ruby class 默认值

Manipulating Ruby class default values

当有多个默认值时,如何只更改第二个初始化变量而不调用第一个?

例如,Ruby class 被创建为 return 类似于掷单个骰子的值,六面骰子的默认值范围为 1 到 6 :

class Die

  def initialize(min=1, max=6)
    @min       = min
    @max       = max
  end

  def roll
    rand(@min..@max)
  end
end

如果我想使用此代码来模拟 return 滚动 20 面骰子,我可以编写以下代码:

p Die.new(min=1, max=20).roll

...但是有没有办法只争论第二个(最大)值?

值得注意 - 这就是我感到困惑的地方(我不完全理解 Ruby class 属性和变量范围) - 如果我调用:

p Die.new(max=20).roll

... 我打印了 nil。 ?。 (我知道这是因为 rand(20..6) returns nil,但我认为 max= 会保留第一个参数的默认最小值 - 而不是 max=20作为绑定到 min= 的整数 20 被摄取...这对我来说似乎很奇怪。)

我想我可以重新设计 Die class 以获取边数的默认值,并设置相对于边数的最小(或最大)值,但这是在旁边我的主要问题的重点是:如何在不显式写入第一个默认值的情况下仅覆盖第二个默认值...

假设大多数骰子的最小值通常为 1,我意识到我可以像这样颠倒最小值和最大值的顺序:

class Die2

  def initialize(max=6, min=1)
    @max       = max
    @min       = min
  end

  def roll
    rand(@min..@max)
  end  
end

...然后像这样调用任何最大边数:

p Die2.new(20).roll

...但是考虑到 class Die 的语法(以及我倾向于在最大值之前写最小值)是否有办法只输入第二个值的参数?或者,也许我接近 Ruby classes 很差?感谢任何帮助或指导 - 谢谢!

在 Ruby 2.0 及更高版本中,您可以使用关键字参数来达到相同的效果:

class Die

  def initialize(min: 1, max: 6)   #<--declare arguments like this
    @min       = min
    @max       = max
  end

  def roll
    rand(@min..@max)
  end
end

p Die.new(max: 20).roll            #<--and call like this

https://repl.it/Dyxn/0

您可以在此 article

中阅读有关关键字参数的更多信息

如果你写

class Die
  def initialize(min=1, max=6)
    @min, @max = min, max
  end
end

并通过传递单个参数创建一个新实例,例如:

die = Die.new(3)
  #=> #<Die:0x007fcc6902a700 @min=3, @max=6>

我们可以从return的值看出参数3已经被赋值给@min并且@max获得了它的默认值。简而言之,要将一个值传递给 @max,您还必须将一个值传递给 @min(当然,除非您颠倒参数的顺序)。

您可以使用命名参数(或命名参数)来做您想做的事情,在Ruby v2 中引入。 0.

class Die
  def initialize(min: 1, max: 6)
    @min, @max = min, max
  end
end

die = Die.new(max: 3)
  #=> #<Die:0x007fcc698ccc00 @min=1, @max=3>

(或die = Die.new(:max=>3)。如您所见,@min 等于其默认值,@max 等于传递的参数,3.

Rubyv2.0 中的关键字参数需要默认值,但 v2.1 扩展了它们的功能以允许所需的命名参数。例如,参见 this article

最后,考虑以下两种情况(第二种比较有趣)。

class Die
  def initialize(min=1, max: 6)
    @min, @max = min, max
  end
end
die = Die.new(max: 3)
  #=> #<Die:0x007fcc69954448 @min=1, @max=3>

class Die
  def initialize(min, max: 6)
    @min, @max = min, max
  end
end
die = Die.new(max: 3)
  #=> #<Die:0x007fa01b900930 @min={:max=>3}, @max=6>