Ruby类实例变量与类变量Ruby类实例变量与类变量(Ruby class instance var

2019-05-06 14:59发布

I read "When do Ruby instance variables get set?" but I'm of two minds when to use class instance variables.

Class variables are shared by all objects of a class, Instance variables belong to one object. There's not much room left to use class instance variables if we have class variables.

Could someone explain the difference between these two and when to use them?

Here's a code example:

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

I understand now, Class Instance Variables are not passed along the inheritance chain!

Answer 1:

在一个类的实例变量:

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] 


Answer 2:

我认为主要的(唯一?)不同的是继承:

class T < S
end

p T.k
=> 23

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

p T.s
=> nil

类变量由所有的“类实例”(即子类)共享的,而类的实例变量是仅专用于该类。 但是,如果你从来没有打算扩展您的类,所不同的是纯学术性的。



Answer 3:

#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


Answer 4:

正如有人说,类变量是给定类及其子类之间共享。 类实例变量属于正好一个类; 它的子类是分开的。

为什么会出现这种现象存在吗? 好了,一切都在Ruby是一个对象,甚至类。 这意味着,每一个类具有类的一个对象Class (或更确切地说,一个子类Class ),对应于它。 (当你说class Foo ,你真的宣布恒定Foo和分配类对象吧。)而且每一个Ruby对象可以有实例变量,因此类对象可以有实例变量了。

麻烦的是,在类对象实例变量并不真正表现通常希望类变量的运行方式。 通常你想用它的子类可以共享父类中定义一个类变量,但是这不是实例变量是如何工作的,子类有它自己的类对象,而这个类对象都有自己的实例变量。 因此,他们引入了你就更有可能想要的行为单独的类变量。

换句话说,类的实例变量有几分Ruby的设计的事故。 你可能,除非你特别想知道他们是你要找的内容不应该使用它们。



Answer 5:

虽然它可能立即似乎有用利用类的实例变量,因为类的实例变量是子类中共享并它们可以同时单和实例方法中被称为,有一个缺点singificant。 它们是共享等子类可以改变类的实例变量的值,和基类也将改变,这通常是不希望的行为的影响:

class C
  @@c = 'c'
  def self.c_val
    @@c
  end
end

C.c_val
 => "c" 

class D < C
end

D.instance_eval do 
  def change_c_val
    @@c = 'd'
  end
end
 => :change_c_val 

D.change_c_val
(irb):12: warning: class variable access from toplevel
 => "d" 

C.c_val
 => "d" 

轨引入了一个名为class_attribute方便的方法。 顾名思义,它声明一个类级别的属性,其价值是由子类继承。 所述class_attribute值可以在两个单和实例方法来访问,如与类实例变量的情况。 然而,随着class_attribute Rails中的巨大优势是子类可以改变自身的价值,也不会影响到父类。

class C
  class_attribute :c
  self.c = 'c'
end

 C.c
 => "c" 

class D < C
end

D.c = 'd'
 => "d" 

 C.c
 => "c" 


文章来源: Ruby class instance variable vs. class variable