class A
attr_accessor :m
def n
@m + 1
end
end
a = A.new
a.m = 4
p a.n
我说的是"n"方法中的代码,其中你有 @m + 1。这种代码是否容易崩溃,因为我没有要求用户为 @m 变量提供值?
作为一般规则,属性应在适当时具有默认值,或者应将值传递到构造函数中。在上述情况下,如果您删除了a.m = 4
行并运行代码,则会收到此错误:
some.rb:5:in `n': undefined method `+' for nil:NilClass (NoMethodError)
from some.rb:10:in `<main>'
对于对象,如果属性没有默认值,则要求通过构造函数传入它们,如果没有默认值,则失败。这确保了无论对象如何实例化,您都将有一个合理的默认值。传递具有这样公开值的对象是代码中的定时炸弹。
你的代码有两点令人不安:
-
您应该通过变量名而不是实例变量名引用
attr_accessor
设置的值,这意味着这样做def n m + 1 # and not @m + 1 end
-
如果一个变量可以
nil
,你应该保护所有涉及它的操作不以某种方式nil
,即使这意味着引发自定义错误,因为"未定义的方法 + 对于 NilClass"不是一个真正的描述性错误。这意味着最好写这样的东西def n raise StandardError.new("m is not set in instance of A") if m.nil? m + 1 end
如果您要寻找错误,这将节省您的时间。此外,如果您有默认值,则可以对
m
使用默认值,但在初始化时对其进行设置:def initialize super() self.m = 3 #or # self.m ||= 3 This would only set m if it wasn't set by initialization in a superclass end
当属性是可选的或不需要生成对象时,请使用基于 setter 的依赖项注入;当生成对象(或其关键功能)需要属性时,使用基于构造函数的依赖项注入。
在您的情况下,如果类的对象唯一要做的就是调用方法 n
然后使用构造函数提供m
否则使用setter