如果我有一个类似的话怎么样?
class Thing
def number
10
end
end
我继承了这样:
class OtherThing < Thing
CONSTANT = number / 2
end
当我尝试实例化类时,我得到undefined local variable or method 'number'
,但如果我这样做:
class OtherThing < Thing
def method_instead_of_constant
number / 2
end
end
有效吗?
修改
我不一定要找一个黑客去做这个工作,而是要理解为什么它没有。 mudasobwa
下面的答案帮助最多;常量是在类级别分配的,而不是在实例上分配。
答案 0 :(得分:3)
因为number
是Thing
上的实例方法。 OtherThing
的类定义的范围是Class
的实例,这意味着它在定义时不是Thing
的实例或OtherThing
的实例。
那就是说,你不应该通过执行方法来定义常量。你可能有一个计算的类变量,你打电话给freeze
以防止在启动后编辑,但即使这不是一个非常常见的模式。
答案 1 :(得分:2)
您需要一个类方法来实现您正在寻找的功能:
class Thing
# ⇓⇓⇓⇓ HERE
def self.number
10
end
end
class OtherThing < Thing
CONSTANT = number / 2
end
CONSTANT
赋值发生在类级别,因此它可以访问Thing
的类方法,但不能访问它的实例方法。
另一方面,您可以实例化Thing
,然后在其上调用实例方法:
class Thing
def number
10
end
end
class OtherThing < Thing
# ⇓⇓⇓⇓⇓⇓⇓⇓⇓ HERE
CONSTANT = Thing.new.number / 2
end
答案 2 :(得分:1)
由于范围。
根据动态范围评估方法调用,并区分类和实例范围。常量在词法范围内被解析,并且不像方法那样区分类和实例范围。
class A
# expressions are evaluated in scope of class A
def m
# expressions are evaluated in scope of an instance of A
return 42
end
end
类和实例不一样。
A
a = A.new
A.class # => Class
a.class # => A
A.respond_to?(:m) # => false
a.respond_to?(:m) # => true
A.m # => raises NoMethodError
a.m # => 42
因此,在类体中,您无法调用实例方法。
然而,使用词法范围查找常量,即源文件中类和模块的周围上下文。
module M
# can access global constants and those defined in M
class A
# can access global constants and those defined in M or A
def m
# can access global constants and those defined in M or A
end
end
end
您可以使用Module.nesting
答案 3 :(得分:1)
我不一定要找一个黑客来完成这项工作,但是[原文如此] 了解它为什么没有。
以下是错误消息:
undefined local variable or method 'number'
当Ruby解释器看到number
时,它会查找局部变量或名为number
的方法。在方法的上下文中,解释器将number
读为self.number
。所以这一行:
CONSTANT = number / 2
实际上被视为:
CONSTANT = self.number / 2
那么self
是什么?
那取决于你明确或隐含地定义它的位置。在类块中,self
是类本身,即OtherThing
。由于OtherThing
或其任何祖先都没有定义类方法number
,因此也没有变量number
,因此Ruby会抛出错误消息。
self
是当前对象。但如果没有实例和更多理论,这是非常抽象的。其他相关主题是 Singleton-Classes 和继承。如果您喜欢书籍,那么我推荐 David A. Black The Well-Grounded Rubyist 2nd Ed,第5章。再想一想,读一读全书。