Programming

루비 클래스 인스턴스 변수와 클래스 변수

procodes 2020. 5. 26. 21:31
반응형

루비 클래스 인스턴스 변수와 클래스 변수


" 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

클래스 인스턴스 변수는 상속 체인을 따라 전달되지 않습니다.


클래스의 인스턴스 변수 :

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] 

나는 주요한 (유일한) 다른 것이 상속이라고 믿는다.

class T < S
end

p T.k
=> 23

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

p T.s
=> nil

클래스 변수는 모든 "클래스 인스턴스"(예 : 서브 클래스)가 공유하는 반면 클래스 인스턴스 변수는 해당 클래스에만 적용됩니다. 그러나 수업을 연장하지 않으려는 경우 그 차이는 순전히 학문입니다.


#class instance variable are available only to class method and not to instance methods whereas class variable are avilable to both instance methods and class methods. Also the class instance variables are lost in inheritance chain whereas class variables are not.

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

As others said, class variables are shared between a given class and its subclasses. Class instance variables belong to exactly one class; its subclasses are separate.

Why does this behavior exist? Well, everything in Ruby is an object—even classes. That means that each class has an object of the class Class (or rather, a subclass of Class) corresponding to it. (When you say class Foo, you're really declaring a constant Foo and assigning a class object to it.) And every Ruby object can have instance variables, so class objects can have instance variables, too.

The trouble is, instance variables on class objects don't really behave the way you usually want class variables to behave. You usually want a class variable defined in a superclass to be shared with its subclasses, but that's not how instance variables work—the subclass has its own class object, and that class object has its own instance variables. So they introduced separate class variables with the behavior you're more likely to want.

In other words, class instance variables are sort of an accident of Ruby's design. You probably shouldn't use them unless you specifically know they're what you're looking for.


While it may immediately seem useful to utilize class instance variables, since class instance variable are shared among subclasses and they can be referred to within both singleton and instance methods, there is a singificant drawback. They are shared and so subclasses can change the value of the class instance variable, and the base class will also be affected by the change, which is usually undesirable behavior:

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" 

Rails introduces a handy method called class_attribute. As the name implies, it declares a class-level attribute whose value is inheritable by subclasses. The class_attribute value can be accessed in both singleton and instance methods, as is the case with the class instance variable. However, the huge benefit with class_attribute in Rails is subclasses can change their own value and it will not impact parent class.

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

 C.c
 => "c" 

class D < C
end

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

 C.c
 => "c" 

Official Ruby FAQ: What is the difference between class variables and class instance variables?

The main difference is the behavior concerning inheritance: class variables are shared between a class and all its subclasses, while class instance variables only belong to one specific class.

Class variables in some way can be seen as global variables within the context of an inheritance hierarchy, with all the problems that come with global variables. For instance, a class variable might (accidentally) be reassigned by any of its subclasses, affecting all other classes:

class Woof

  @@sound = "woof"

  def self.sound
    @@sound
  end
end

Woof.sound  # => "woof"

class LoudWoof < Woof
  @@sound = "WOOF"
end

LoudWoof.sound  # => "WOOF"
Woof.sound      # => "WOOF" (!)

Or, an ancestor class might later be reopened and changed, with possibly surprising effects:

class Foo

  @@var = "foo"

  def self.var
    @@var
  end
end

Foo.var  # => "foo" (as expected)

class Object
  @@var = "object"
end

Foo.var  # => "object" (!)

So, unless you exactly know what you are doing and explicitly need this kind of behavior, you better should use class instance variables.

참고URL : https://stackoverflow.com/questions/15773552/ruby-class-instance-variable-vs-class-variable

반응형