2010-09-27 193 views

回答

132

类变量(@@)在该类及其所有后代中共享。类实例变量(@)不被类的后代共享。


类变量(@@

让我们有一个类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和酒吧有@@i相同的值:

p Foo.i # => 1 
p Bar.i # => 1 

和不断变化的@@i在一个改变它在两个:

Bar.i = 2 
p Foo.i # => 2 
p Bar.i # => 2 

类实例变量(@

让我们用一个类实例va做一个简单的类可变结构@i和存取读取和写入@i

class Foo 

    @i = 1 

    def self.i 
    @i 
    end 

    def self.i=(value) 
    @i = value 
    end 

end 

而派生类:

class Bar < Foo 
end 

我们看到,虽然酒吧继承了@i访问器,它不继承@i本身:

p Foo.i # => 1 
p Bar.i # => nil 

我们可以设置Bar的@i而不影响Foo的@i

Bar.i = 2 
p Foo.i # => 1 
p Bar.i # => 2 
+0

为什么使用类方法返回实例变量? 你经常遇到这种情况吗? – sekmo 2017-05-13 10:25:21

+0

@sekmo这些示例中的访问器返回属于类的_class实例变量_或属于类层次结构的_class variables_。它们不会返回属于该类实例的纯_实例变量_。术语“实例变量”,“类实例变量”和“类变量”相当混乱,不是吗? – 2017-05-13 16:03:32

59

首先,你必须明白,类实例太 - 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 variables,因为上面的奇怪的行为,并建议使用class instance variables代替。

+0

+1用于概述这些类是“Class”的实例。 – mikezter 2010-09-27 15:15:45

+1

+1超级解释!这是每个Ruby新手程序员都应该消化的东西。 – TomZ 2011-11-11 15:08:37