Örnek değişkeni: self vs @


179

İşte bazı kod:

class Person
  def initialize(age)
    @age = age
  end

  def age
    @age
  end

  def age_difference_with(other_person)
    (self.age - other_person.age).abs
  end

  protected :age
end

Ne bilmek istiyorum kullanarak arasındaki farktır @ageve self.ageiçinde age_difference_withyöntemle.

Yanıtlar:


260

Yazma @age, örnek değişkenine doğrudan erişir @age. Yazma self.age, nesneye age, genellikle örnek değişkeni döndürecek olan iletiyi göndermesini söyler @age- ancak ageyöntemin belirli bir alt sınıfta nasıl uygulandığına bağlı olarak çok sayıda başka şey yapabilir . Örneğin, her zaman olduğundan 10 yaş daha küçük olduğunu bildiren bir MiddleAgedSocialite sınıfınız olabilir. Ya da daha pratik olarak, bir PersistentPerson sınıfı, kalıcı bir mağazadan bu verileri tembel olarak okuyabilir, tüm kalıcı verilerini bir karma içinde önbelleğe alabilir.


2
Bir zamanlar raylarda bir kitap okudum ve bu öz ve @ arasındaki farkı anlamıyorum, bu yüzden her zaman yöntemlerimde (ayarlayıcı ve alıcı değil) self.var_name'yi genel arayüzü kullanarak yapmak için kullanmalıyım, ben alıcı ve belirleyicide tanımlamak için zaman harcadı, değil mi?
sarunw

1
... türkçe ... herhangi bir sayı ile ne demek istiyorsun. verilen son iki örneği alamadım.
user2167582

23

Fark, yöntemin kullanımını, uygulanmasından ayırmasıdır. Mülkün uygulaması değişecek olsaydı - doğum tarihini tutmayı ve sonra şimdi ve doğum tarihi arasındaki zaman farkına göre yaşı hesaplamayı - varsa, yönteme bağlı olan kodun değişmesine gerek yoktur. Özelliği doğrudan kullandıysa, değişikliğin kodun diğer alanlarına yayılması gerekir. Bu anlamda, özelliği doğrudan kullanmak, sınıf tarafından sağlanan arabirimi kullanmaktan daha kırılgandır.


15
Ohhh, çünkü self.age bir örnek değişkenine veya bir örnek yöntemine başvurabilir mi?
Nolan Amy

@. @ ... üzgün bu durumda
cyc115

7

Struct.newBir intializer oluşturmanın temiz bir yolu olan bir sınıfı devraldığınızda uyarılırsınız ( Ruby'de başlatıcı nasıl oluşturulur? )

class Node < Struct.new(:value)
    def initialize(value)
        @value = value
    end
    def show()
        p @value
        p self.value # or `p value`
    end
end 

n = Node.new(30)
n.show()

dönecek

30
nil

Ancak, başlatıcıyı çıkardığınızda,

nil
30

Sınıf tanımı ile

class Node2
    attr_accessor :value
    def initialize(value)
        @value = value
    end
    def show()
        p @value
        p self.value
    end
end

Yapıcıyı sağlamalısınız.

n2 = Node2.new(30)
n2.show()

dönecek

30
30

@Prosseek örneği için teşekkürler, şu anda Ruby on Rails'i öğreniyorum ve bu tam olarak Ruby'nin gereksiz yere karmaşık olduğunu hissettiren davranış türüdür.
cyc115

3

İlk cevap tamamen doğrudur, ancak göreceli bir acemi olarak ne ima ettiğini hemen anlayamadım (kendime mesaj göndermek? Uh huh ...). Kısa bir örneğin yardımcı olacağını düşünüyorum:

class CrazyAccessors
  def bar=(val)
    @bar = val - 20 # sets @bar to (input - 20)
  end
  def bar
    @bar
  end

  def baz=(value)
    self.bar = value # goes through `bar=` method, so @bar = (50 - 20)
  end

  def quux=(value)
    @bar = value     # sets @bar directly to 50
  end
end

obj  = CrazyAccessors.new
obj.baz = 50
obj.bar  # => 30
obj.quux = 50
obj.bar  # => 50

8
Bu örnek işleri daha karmaşık hale getirdi.
Oskar Holmkratz

1
Üzgünüm ama örnek benim için yeterince yorum yapılmamış. Aklını takip edemem.
kouty

Smalltalk'tan gelen biri, bir nesnenin "kendisine mesaj gönderdiğini" söyleyecektir. Python'dan gelen biri, bir nesnenin "kendi başına bir yöntem çağırdığını" söyleyecektir. Kafanız karışmasın; tamamen aynı şeyler. (Anlambilimsel bir purist, yalnızca dinamik yazım içeren diller için aynı olduklarına ve bir C ++ sanal yöntem çağrısının bir ileti göndermekle tamamen aynı olmadığına itiraz edebilir. cevap.)
GrandOpener

Örneği seviyorum ama lütfen gerçekte neler olduğuna dair biraz daha yorum yapın. Hiçbir açıklama ile zor
CalamityAdam

2

Hiçbir fark yok. Sadece görmenin self.ageve other_person.agebirbirine yakın olmanın belgesel değeri için yapıldığından şüpheleniyorum .

Bu kullanımın gerçek bir alıcının gelecekte yazılmasına izin verdiğini varsayalım, bu sadece bir örnek değişkeni döndürmekten daha karmaşık bir şey yapabilir ve bu durumda yöntemin değişmesi gerekmez.

Ancak bu, endişelenmesi olası bir soyutlamadır, sonuçta, eğer nesnenin uygulanması değiştiyse, diğer yöntemleri değiştirmek mantıklıdır, bir noktada nesnenin içindeki basit bir referans mükemmel bir şekilde makul.

Her halükarda, agemülkün soyutlanması hala açık kullanımını açıklamamaktadır self, çünkü sadece düz agede erişimciyi çağırırdı.


-3

@age - kesinlikle örnek değişken yaştır

self.age - örnek özellik yaşını belirtir.

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.