谁能告诉我类变量和类实例变量之间的区别?
问问题
33021 次
3 回答
157
类变量 ( @@
) 在类及其所有后代之间共享。类实例变量 ( @
) 不被类的后代共享。
类变量 ( @@
)
让我们有一个类 Foo 和一个类变量@@i
,以及用于读写的访问器@@i
:
class Foo
@@i = 1
def self.i
@@i
end
def self.i=(value)
@@i = value
end
end
和一个派生类:
class Bar < Foo
end
我们看到 Foo 和 Bar 具有相同的值@@i
:
p Foo.i # => 1
p Bar.i # => 1
改变@@i
一个改变它在两个方面:
Bar.i = 2
p Foo.i # => 2
p Bar.i # => 2
类实例变量 ( @
)
让我们用一个类实例变量@i
和用于读写的访问器创建一个简单的类@i
:
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
和一个派生类:
class Bar < Foo
end
我们看到虽然 Bar 继承了 的访问器@i
,但它并没有继承@i
自己:
p Foo.i # => 1
p Bar.i # => nil
我们可以在@i
不影响 Foo 的情况下设置 Bar @i
:
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
于 2010-09-27T10:48:12.897 回答
73
首先你必须明白类也是实例——类的实例Class
。
一旦你理解了这一点,你就可以理解一个类可以有与之关联的实例变量,就像一个普通的(阅读:非类)对象一样。
Hello = Class.new
# setting an instance variable on the Hello class
Hello.instance_variable_set(:@var, "good morning!")
# getting an instance variable on the Hello class
Hello.instance_variable_get(:@var) #=> "good morning!"
请注意,实例变量 on 与实例上的实例变量完全无关Hello
且不同Hello
hello = Hello.new
# setting an instance variable on an instance of Hello
hello.instance_variable_set(:@var, :"bad evening!")
# getting an instance variable on an instance of Hello
hello.instance_variable_get(:@var) #=> "bad evening!")
# see that it's distinct from @var on Hello
Hello.instance_variable_get(:@var) #=> "good morning!"
另一方面,类变量是上述两者的一种组合,因为它可以在自身及其Hello
实例以及子类Hello
及其实例上访问:
HelloChild = Class.new(Hello)
Hello.class_variable_set(:@@class_var, "strange day!")
hello = Hello.new
hello_child = HelloChild.new
Hello.class_variable_get(:@@class_var) #=> "strange day!"
HelloChild.class_variable_get(:@@class_var) #=> "strange day!"
hello.singleton_class.class_variable_get(:@@class_var) #=> "strange day!"
hello_child.singleton_class.class_variable_get(:@@class_Var) #=> "strange day!"
很多人说要避免class variables
,因为上面的奇怪行为,并推荐使用class instance variables
代替。
于 2010-09-27T10:54:29.570 回答
0
另外我想补充一点,您可以从类@@
的任何实例访问类变量 ()
class Foo
def set_name
@@name = 'Nik'
end
def get_name
@@name
end
end
a = Foo.new
a.set_name
p a.get_name # => Nik
b = Foo.new
p b.get_name # => Nik
但是你不能对类实例变量(@
)做同样的事情
class Foo
def set_name
@name = 'Nik'
end
def get_name
@name
end
end
a = Foo.new
a.set_name
p a.get_name # => Nik
b = Foo.new
p b.get_name # => nil
于 2019-01-15T08:52:23.383 回答