ruby - 为什么 Ruby 编译器在这种情况下将预期的参数数量计算为零?
问题描述
我对 Ruby 很陌生,在定义类的对象时遇到了问题。如果我理解正确, def initialize 应该要求三个计算,但是代码编译时会出现错误,给出三个,但它期望零值。
我以为 attr_accessor 会出现错误,但快速测试表明情况并非如此。
红宝石版本是 2.6.4
test.rb:16:in `new':参数数量错误(给定 3,预期为 0)(ArgumentError)
class Battler
attr_accessor :health, :damage, :armor,
def initialize(health, damage, armor)
@health = health
@damage = damage
@armor = armor
end
def able?
return @health > 0
end
end
knight = Battler.new(1000, 10, 3)
goblin = Battler.new(20, 6, 1)
问题开始于
knight = Battler.new(1000, 10, 3)
解决方案
您可能知道attr_accessor
接受符号列表(或字符串),并且为每一个定义了两个方法:所谓的 setter(例如health=
)和 getter(health
)。列表(不是实际的类型顺便说一句。)是一个或多个用逗号分隔的表达式,因此在您的情况下,Ruby 期望后面有另一个表达式,:armor
因为您在后面加上了一个逗号。
(如果尾随逗号是故意的,请告诉我们。一些程序员在某些情况下(并且取决于语言)使用并推荐它们。尽管这会使任何答案变得更复杂,因为 Ruby 实际上对它们很好 - 只是不在这个案子。)
然而,这只是你的错误解释的一部分。作为一种编程语言,Ruby 最基本的特性之一是几乎所有东西都有一个值(表达式)。例如,尝试x = if ...
使用其他语言!它通常不起作用,因为许多语言都有 if 语句,而不是 if 表达式。
在 Ruby 中,方法定义也是表达式:通过def
( def foo; end
) 定义用于返回的方法nil
。由于 Ruby 2.1 方法定义返回方法的名称 ( :foo
)。现在,def-expressions 的返回值对您来说似乎不是很有用,而且在很多情况下也不是很有用,但您可能同意方法名称 ( :foo
) 肯定比nil
.
其主要用例是 , , 等方法private
,public
它们method_function
不是关键字,而是像一个关键字一样使用(它们的定义特征是省略括号的调用):
private def foo
end
# before 2.1
private # from now on every method in this class context will be private
def foo
end
# or
def foo
end
private :foo # only foo will be private but we have to repeat the name
我们的朋友attr_accessor
也是这样一个类似关键字的方法,但def
表达式的值在这里更重要。请记住,它是作为符号的方法名称。您写道(简化):
attr_accessor :health, :damage, :armor,
def initialize(health, damage, armor)
end
# which after the method was defined becomes
attr_accessor :health, :damage, :armor, :initialize
为了让它更清楚一点 - 没有attr_accessor
你的代码可能看起来像这样:
class Battler
def initialize(health, damage, armor) # takes 3 required arguments
end
def health
@health
end
def health=(v)
@health = v
end
# damage, armor
def initialize # takes no arguments
@initialize
end
def initialize=(v)
@initialize = v
end
end
你看到你正在重新定义Battler#initialize
,而你的新定义不接受争论,因为 getter 通常不接受。
重新定义不会被视为错误,因为它们可能是故意的,但是 Ruby 可以为您发出警告。ruby -w test.rb
在命令行上运行,它会输出:
test.rb:15: warning: assigned but unused variable - knight test.rb:16: warning: assigned but unused variable - goblin test.rb:2: warning: method redefined; discarding old initialize test.rb:3: warning: previous definition of initialize was here Traceback (most recent call last): 1: from test.rb:15:in `<main>' test.rb:15:in `new': wrong number of arguments (given 3, expected 0) (ArgumentError)
在这里您可以看到在第 2 行initialize
中,最初在第 3 行中定义的方法被重新定义。如果您对这里为什么第 3 行在第 2 行之前感到困惑,那么请记住,方法定义是传递给的列表的一部分,attr_accessor
因此必须在调用之前评估 def-expr。
推荐阅读
- python - 在python中以相同的单位制作数字浮点数
- google-cloud-firestore - 使用firestore作为数据库时如何从datagridview中搜索值
- r - 使用R从具有字符串和数字数据的变量中提取数字
- reactjs - Formik onChange 执行但不更改字段值?
- css - 更改工具提示 CSS bootstrap 4 的样式
- html - 如何将中心的文本与 SVG 元素对齐?
- html - 扩展菜单区域内输入框的悬停区域
- angular - 访问 div 外的 ngform 时出现错误 TS2339
- ios - 使用 Combine 框架向 UIViewController 添加分页以实现无限滚动
- flutter - Flutter:持久的底部导航在选项卡更改时重建子页面