135

我讀的是「When do Ruby instance variables get set?」,但我有兩個使用類實例變量的想法。Ruby類實例變量與類變量

類變量由類的所有對象共享,實例變量屬於一個對象。如果我們有類變量,那麼沒有多少空間可以使用類實例變量。

有人可以解釋這兩者之間的差異以及何時使用它們?

下面是一個代碼示例:

class S 
    @@k = 23 
    @s = 15 
    def self.s 
    @s 
    end 
    def self.k 
    @@k 
    end 

end 
p S.s #15 
p S.k #23 

我現在明白了,類的實例變量不沿着繼承鏈過去了!

回答

195

實例變量:

class Parent 
    @things = [] 
    def self.things 
    @things 
    end 
    def things 
    self.class.things 
    end 
end 

class Child < Parent 
    @things = [] 
end 

Parent.things << :car 
Child.things << :doll 
mom = Parent.new 
dad = Parent.new 

p Parent.things #=> [:car] 
p Child.things #=> [:doll] 
p mom.things #=> [:car] 
p dad.things #=> [:car] 

類變量:

class Parent 
    @@things = [] 
    def self.things 
    @@things 
    end 
    def things 
    @@things 
    end 
end 

class Child < Parent 
end 

Parent.things << :car 
Child.things << :doll 

p Parent.things #=> [:car,:doll] 
p Child.things #=> [:car,:doll] 

mom = Parent.new 
dad = Parent.new 
son1 = Child.new 
son2 = Child.new 
daughter = Child.new 

[ mom, dad, son1, son2, daughter ].each{ |person| p person.things } 
#=> [:car, :doll] 
#=> [:car, :doll] 
#=> [:car, :doll] 
#=> [:car, :doll] 
#=> [:car, :doll] 

在某一類(而不是在這個類的一個實例)的實例變量可以共同之處存儲到沒有子類的類也會自動獲取它們(反之亦然)。通過類變量,您可以方便地不必從實例對象中編寫self.class,並且(如果需要)還可以在整個類層次結構中自動共享。在行動

class Parent 
    @@family_things = [] # Shared between class and subclasses 
    @shared_things = [] # Specific to this class 

    def self.family_things 
    @@family_things 
    end 
    def self.shared_things 
    @shared_things 
    end 

    attr_accessor :my_things 
    def initialize 
    @my_things = []  # Just for me 
    end 
    def family_things 
    self.class.family_things 
    end 
    def shared_things 
    self.class.shared_things 
    end 
end 

class Child < Parent 
    @shared_things = [] 
end 

然後:


一起合併到這些單個的例子,還包括基於實例的實例變量

mama = Parent.new 
papa = Parent.new 
joey = Child.new 
suzy = Child.new 

Parent.family_things << :house 
papa.family_things << :vacuum 
mama.shared_things << :car 
papa.shared_things << :blender 
papa.my_things  << :quadcopter 
joey.my_things  << :bike 
suzy.my_things  << :doll 
joey.shared_things << :puzzle 
suzy.shared_things << :blocks 

p Parent.family_things #=> [:house, :vacuum] 
p Child.family_things #=> [:house, :vacuum] 
p papa.family_things #=> [:house, :vacuum] 
p mama.family_things #=> [:house, :vacuum] 
p joey.family_things #=> [:house, :vacuum] 
p suzy.family_things #=> [:house, :vacuum] 

p Parent.shared_things #=> [:car, :blender] 
p papa.shared_things #=> [:car, :blender] 
p mama.shared_things #=> [:car, :blender] 
p Child.shared_things #=> [:puzzle, :blocks] 
p joey.shared_things #=> [:puzzle, :blocks] 
p suzy.shared_things #=> [:puzzle, :blocks] 

p papa.my_things  #=> [:quadcopter] 
p mama.my_things  #=> [] 
p joey.my_things  #=> [:bike] 
p suzy.my_things  #=> [:doll] 
30

相信主(僅?)不同是繼承:

class T < S 
end 

p T.k 
=> 23 

S.k = 24 
p T.k 
=> 24 

p T.s 
=> nil 

類變量由所有「類實例」(即子類)共享的,而類的實例變量是僅專用於該類。但是,如果你永遠不打算延長你的課程,那麼差別純粹是學術。一類

18

#class實例變量只適用於類方法,而不是實例方法,而類變量可用於實例方法和類方法。此外,類實例變量在繼承鏈中丟失,而類變量不是。

class Vars 

    @class_ins_var = "class instance variable value" #class instance variable 
    @@class_var = "class variable value" #class variable 

    def self.class_method 
    puts @class_ins_var 
    puts @@class_var 
    end 

    def instance_method 
    puts @class_ins_var 
    puts @@class_var 
    end 
end 

Vars.class_method 

puts "see the difference" 

obj = Vars.new 

obj.instance_method 

class VarsChild < Vars 


end 

VarsChild.class_method 
12

正如其他人所說,類變量是在給定的類和它的子類之間共享的。類實例變量只屬於一個類;它的子類是分開的。

爲什麼這種行爲存在?那麼,Ruby中的所有東西都是一個對象 - 甚至是類。這意味着每個類都有一個對應於它的類Class(或者更確切地說,Class的子類)的對象。 (當你說class Foo時,你確實聲明瞭一個常量Foo併爲它分配一個類對象。)每個Ruby對象都可以有實例變量,所以類對象也可以有實例變量。

問題是,類對象上的實例變量實際上並不像您通常希望類變量行爲的那樣行爲。您通常希望在超類中定義的類變量與其子類共享,但這不是實例變量的工作方式 - 子類具有自己的類對象,並且該類對象具有自己的實例變量。所以他們引入了單獨的類變量和更可能需要的行爲。

換句話說,類實例變量是Ruby設計中的一種意外。除非你明確知道你在找什麼,否則你可能不應該使用它們。

+0

所以類變量就像Java中的靜態變量? –