Ruby 类变量和类实例变量之间的区别?
有谁能告诉我类变量和类实例变量之间的区别吗?类变量(Ruby 类变量和类实例变量之间的区别?,ruby,class-variables,class-instance-variables,Ruby,Class Variables,Class Instance Variables,有谁能告诉我类变量和类实例变量之间的区别吗?类变量(@)在类及其所有子体之间共享。类的子体不共享类实例变量(@) 类变量(@) 让我们有一个带有类变量@@i的类Foo,以及用于读写@@i的访问器: class Foo @@i = 1 def self.i @@i end def self.i=(value) @@i = value end end p Foo.i # => 1 p Bar.i # => 1 class Fo
@
)在类及其所有子体之间共享。类的子体不共享类实例变量(@
)
类变量(
@
)
让我们有一个带有类变量@@i
的类Foo,以及用于读写@@i
的访问器:
class Foo
@@i = 1
def self.i
@@i
end
def self.i=(value)
@@i = value
end
end
p Foo.i # => 1
p Bar.i # => 1
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
和派生类:
class Bar < Foo
end
class Bar < Foo
end
一次更改@@i
会同时更改两个:
Bar.i = 2
p Foo.i # => 2
p Bar.i # => 2
类实例变量(
@
)
让我们用class实例变量@i
和用于读写@i
的访问器创建一个简单的类:
class Foo
@@i = 1
def self.i
@@i
end
def self.i=(value)
@@i = value
end
end
p Foo.i # => 1
p Bar.i # => 1
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
和派生类:
class Bar < Foo
end
class Bar < Foo
end
我们可以设置条形图的@i
,而不影响Foo的@i
:
class Foo
@@i = 1
def self.i
@@i
end
def self.i=(value)
@@i = value
end
end
p Foo.i # => 1
p Bar.i # => 1
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
首先,您必须了解类也是实例——
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!"
请注意,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 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
但是不能对类实例变量(@
)执行相同的操作
+超级解释!这是每个刚接触Ruby的程序员都应该理解的东西。为什么要使用类方法返回实例变量?您经常遇到这种情况吗?@sekmo这些示例中的访问器返回属于类的类实例变量或属于类层次结构的类变量。它们不返回属于类实例的普通实例变量。术语“实例变量”、“类实例变量”和“类变量”非常容易混淆,不是吗?-1:这是错误的:类实例变量可以从该类的每个实例访问(前提是存在访问器)。此外,您的示例显示的是常规实例变量,而不是类实例变量。类实例变量是在方法之外声明的,它与常规实例变量和类变量都有根本的不同。如何从该类的每个实例访问类实例变量?你读过Wayne Conrad的答案吗?这从字面上解释了这一点。我知道您可以从类方法(如
Foo.I
)获得访问权限,但是如何使用\class
对此类的每个实例(如Foo.new.I
)进行相同的访问呢。我个人认为,当调用除self之外的任何东西时,#class
的用法都是代码气味。您甚至可以更进一步,实现实例访问器i
和i=
,它们将委托给它们的#类
等价物,在这种情况下,您可以执行Foo.new.i
。我不建议这样做,因为它会创建一个令人困惑的接口,表明您正在修改一个对象成员。