Sınıf değişkenleri ve sınıf örneği değişkenleri arasındaki fark?


Yanıtlar:


152

Bir sınıf değişkeni ( @@), sınıf ve onun tüm soyundan gelenler arasında paylaşılır. Bir sınıf örneği değişkeni ( @), sınıfın soyundan gelenler tarafından paylaşılmaz.


Sınıf değişkeni ( @@)

Sınıf değişkenine sahip bir sınıf Foo @@ive okuma ve yazma için erişimciler edelim @@i:

class Foo

  @@i = 1

  def self.i
    @@i
  end

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

end

Ve türetilmiş bir sınıf:

class Bar < Foo
end

Foo ve Bar'ın aşağıdakiler için aynı değere sahip olduğunu görüyoruz @@i:

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

Ve @@ibirinde değiştirmek onu ikisinde de değiştirir:

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

Sınıf örneği değişkeni ( @)

Bir sınıf örnek değişkeni @ive okuma ve yazma için erişimcilerle basit bir sınıf yapalım @i:

class Foo

  @i = 1

  def self.i
    @i
  end

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

end

Ve türetilmiş bir sınıf:

class Bar < Foo
end

Bar'ın erişimcileri miras almasına rağmen @i, @ikendisini miras almadığını görüyoruz :

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

@iFoo'ları etkilemeden Bar'ı ayarlayabiliriz @i:

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

1
Sınıf yöntemlerini kullanarak neden örnek değişkenleri döndürülsün? Bu durumla sık sık karşılaşıyor musunuz?
sekmo

1
@sekmo Bu örneklerdeki erişimciler, sınıfa ait sınıf örneği değişkenlerini veya sınıf hiyerarşisine ait sınıf değişkenlerini döndürür . Sınıfın örneklerine ait düz örnek değişkenleri döndürmezler . "Örnek değişkeni", "sınıf örneği değişken" ve "sınıf değişkeni" terimleri oldukça kafa karıştırıcı, değil mi?
Wayne Conrad

72

Öncelikle, sınıfların da örnek olduğunu anlamalısınız - Classsınıfın örnekleri .

Bunu anladıktan sonra, bir sınıfın, normal (okuma: sınıf dışı) bir nesnenin yapabildiği gibi kendisiyle ilişkilendirilmiş örnek değişkenlerine sahip olabileceğini anlayabilirsiniz.

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!"

Bir örneği değişken unutmayın Hello, bir de bir örnek değişkeni tamamen ilişkisiz ve farklı örnek arasındaHello

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!"

Öte yandan bir sınıf değişkeni , Hellokendisinde ve örneklerinde ve ayrıca alt sınıflarında ve örneklerinde erişilebildiği için yukarıdaki ikisinin bir tür kombinasyonudur 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!"

Birçok insan class variablesyukarıdaki garip davranış nedeniyle kaçınılması gerektiğini söylüyor ve class instance variablesbunun yerine kullanılmasını tavsiye ediyor .


2
+1 Süper Açıklama! Bu, Ruby'de yeni olan her programcının sindirmesi gereken bir şeydir.
TomZ

0

Ayrıca, sınıfın @@herhangi bir örneğinden sınıf değişkenine ( ) erişebileceğinizi de eklemek istiyorum.

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

Ancak aynı şeyi sınıf örneği değişkeni ( @) için yapamazsınız

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 # => nil

-1: Bu yanlış: sınıf örneği değişkenlerine, o sınıfın her örneğinden erişilebilir (erişimcilerin mevcut olması koşuluyla). Ayrıca, örneğiniz, sınıf örneği değişkenlerini değil, normal örnek değişkenlerini gösterir. Sınıf örneği değişkenleri yöntemlerin dışında bildirilir ve hem normal örnek değişkenlerinden hem de sınıf değişkenlerinden temelde farklıdır.
The Pellmeister

Bu sınıfın her örneğinden sınıf örneği değişkenlerine nasıl erişebilirsiniz?
Evan Ross

Wayne Conrad'ın cevabını okudunuz mu? Bu kelimenin tam anlamıyla açıklıyor. stackoverflow.com/a/3803089/439592
The Pellmeister

Gibi sınıf yöntemlerinden erişebileceğinizi biliyorum Foo.i, ancak bu sınıfın her örneği için aynısını nasıl yapabilirsiniz Foo.new.i?
Evan Ross

Kullanarak #class. Kişisel #classolarak herhangi bir şey çağrıldığında kullanım olduğunu düşünüyorum ama selfkod kokuyor. Hatta bir adım daha ileri gidebilir ve örnek erişimcileri uygulayabilir ive i=bu temsilciyi #classeşdeğerlerine atayabilirsiniz, bu durumda yapabilirsiniz Foo.new.i. Bunu, bir nesne üyesini değiştirdiğinizi düşündüren kafa karıştırıcı bir arayüz oluşturduğu için yapmanızı önermiyorum.
The Pellmeister
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.