如果我有以下 Ruby 代码:
class Blah
def self.bleh
@blih = "Hello"
@@bloh = "World"
end
end
@blih 和 @@bloh 到底是什么?@blih 是 Blah 类中的实例变量,@@bloh 是 Blah 类中的类变量,对吗?这是否意味着@@bloh 是Blah 的类Class 中的一个变量?
如果我有以下 Ruby 代码:
class Blah
def self.bleh
@blih = "Hello"
@@bloh = "World"
end
end
@blih 和 @@bloh 到底是什么?@blih 是 Blah 类中的实例变量,@@bloh 是 Blah 类中的类变量,对吗?这是否意味着@@bloh 是Blah 的类Class 中的一个变量?
人们似乎忽略了该方法是类方法。
@blih 将是常量 Bleh 的类 Class 实例的实例变量。因此:
irb(main):001:0> class Bleh
irb(main):002:1> def self.bleh
irb(main):003:2> @blih = "Hello"
irb(main):004:2> @@blah = "World"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> Bleh.instance_variables
=> []
irb(main):008:0> Bleh.bleh
=> "World"
irb(main):009:0> Bleh.instance_variables
=> ["@blih"]
irb(main):010:0> Bleh.instance_variable_get :@blih
=> "Hello"
@@blah 将作为 Bleh 的类变量提供:
irb(main):017:0> Bleh.class_variables
=> ["@@blah"]
irb(main):018:0> Bleh.send :class_variable_get, :@@blah
=> "World"
有一种方法可以解决这种疯狂......
class Example
@foo # class instance variable
@@bar # class variable
def fun1
@baz # instance variable
end
end
实例变量(在示例@foo
中@baz
)始终以 开头@
,并且它们始终属于self 所指的任何对象:类的对象或表示类的 Class 对象。类定义或类方法中的实例变量引用与实例方法中的实例变量引用完全不同。
继承
因为实例变量不是由类定义的,所以它们与继承机制无关——它们只是在为它们赋值时创建。类实例变量,只是表示类的 Class 对象的实例变量,因此不会被继承。
类变量对类方法和类的实例方法以及类定义本身都是可见和共享的。类变量可以在实例方法、类方法和类定义本身中使用,在任何方法之外。类变量总是根据封闭类定义语句创建的类对象进行评估。
类实例变量的一个缺点是它们不能像类变量一样在实例方法中使用。另一个缺点是可能会将它们与普通实例变量混淆。类实例变量优于类变量的一个优势在于,在对现有类进行子类化时类变量的令人困惑的行为:如果一个类使用类变量,那么任何子类都可以通过更改值来改变该类及其所有后代的行为共享类变量。这是使用类实例变量而不是类变量的有力论据。
其中大部分来自优秀的“The Ruby Programming Language”
以两个 at 符号为前缀的变量是类变量,可在类的实例和类方法中访问。
例子:
class CountEm
@@children = 0
def initialize
@@children += 1
@myNumber = @@children
end
def whoAmI
"I'm child number #@myNumber (out of #@@children)"
end
def CountEm.totalChildren
@@children
end
end
c1 = CountEm.new
c2 = CountEm.new
c3 = CountEm.new
c1.whoAmI # -> "I'm child number 1 (out of 3)"
c3.whoAmI # -> "I'm child number 3 (out of 3)"
CountEm.totalChildren # -> 3
来自链接文本的示例
[为清楚起见编辑]
在您的示例设置中,@blih 在您的类方法范围之外将不可见,因为在类方法内部没有实例可以将实例变量绑定到它。
说到术语,我会说“@@bloh 是 Blah 类中的类变量”,而不是“Blah 类中的变量”。类“类”保持不变。