Soru Neden benzer göründüğünde, eigenclass self.class'a eşdeğer değil?


Notu bir yerlerde özledim ve umarım bunu bana açıklarsın.

Neden bir nesnenin eigenclassı farklıdır self.class?

class Foo
  def initialize(symbol)
    eigenclass = class << self
      self
    end
    eigenclass.class_eval do
      attr_accessor symbol
    end
  end
end

Eigenclass ile eşit olan mantığım trenim class.self oldukça basit:

class << self örnek yöntemlerden ziyade sınıf yöntemlerini bildirmenin bir yoludur. Bu bir kısayol def Foo.bar.

Yani sınıf nesnesine yapılan referansta, geri dönüş self aynı olmalıdır self.class. Bunun nedeni ise class << self ayarlanacak self için Foo.class Sınıf yöntemleri / özniteliklerin tanımı için.

Kafam karıştı mı? Yoksa bu Ruby'nin meta programlamasının gizli bir numarası mı?


76
2017-10-27 13:31


Menşei




Cevaplar:


class << self sınıf yöntemlerini bildirmenin bir yoludur (bu şekilde de kullanılabilir). Muhtemelen aşağıdaki gibi bir kullanım gördünüz:

class Foo
  class << self
    def a
      print "I could also have been defined as def Foo.a."
    end
  end
end

Bu çalışır ve eşdeğerdir def Foo.aama çalışma şekli biraz ince. Sırrı bu selfBu bağlamda, nesneyi ifade eder Foosınıfının benzersiz, anonim bir alt sınıfıdır. Class. Bu alt sınıf çağrılır Foo'ler eigenclass. Yani def a adında yeni bir yöntem oluşturur a içinde Foonormal yöntem çağrısı sözdizimi tarafından erişilen eigenclass: Foo.a.

Şimdi başka bir örneğe bakalım:

str = "abc"
other_str = "def"

class << str
  def frob
    return self + "d"
  end
end

print str.frob # => "abcd"
print other_str.frob # => raises an exception, 'frob' is not defined on other_str

Bu örnek, sonuncusuyla aynıdır, ilk başta söylemek zor olsa da. frob tanımlı değil String sınıf, ama eigenclass str, benzersiz bir anonim alt sınıf String. Yani str bir var frob yöntem, ancak örnekleri String Genel olarak değil. Ayrıca String yöntemlerini geçersiz kılabiliriz (bazı zorlu test senaryolarında çok kullanışlıdır).

Şimdi orijinal örneğinizi anlamak için donanımlıyız. içeride Foobaşlangıç ​​yöntemi self derse değil Fooama bazılarına göre örnek arasında Foo. Eigenclass bir alt sınıfıdır Foo, ama öyle değil Foo; olamazdı, ya da ikinci örnekte gördüğümüz hile işe yaramadı. Yani örneğinize devam etmek için:

f1 = Foo.new(:weasels)
f2 = Foo.new(:monkeys)

f1.weasels = 4 # Fine
f2.monkeys = 5 # Also ok
print(f1.monkeys) # Doesn't work, f1 doesn't have a 'monkeys' method.

Bu yardımcı olur umarım.


114
2017-10-27 13:59



Her bir örnek sınıf oluşturulan sınıfın anonim bir alt sınıfıdır. f1'in sınıfı, Foo'nun anonim alt sınıfıdır, Foo'nun sınıfı, sınıfın anonim bir alt sınıfıdır. - David Seiler
güzel cevap :) Bir çok insan bunu sizin kadar net olarak anlamıyor. - horseyguy
Cevabını okuyana kadar bunu gerçekten anlamadım! :) - Nikki Erwin Ramirez
F1 eigenclassı, kavramsal olarak, f1'in gerçek örneğinden nasıl farklıdır. Eğer f1, eigenclass yöntemlerine erişebilecek tek örnekse, f1 ve onun eigenclass kırılması arasındaki ayrım değil midir? - elju
@elju Evet, kinda. Gerçekten önemli ayrım "Foo" ve "f1'in eigenclass" arasındadır; Eğer varsa, muhtemelen iyisin. - David Seiler


En basit cevap: eigenclass başlatılamıyor.

class F
 def eigen
  class << self 
   self
  end
 end
end
F.new.eigen.new #=> TypeError: can't create instance of virtual class

44
2017-11-16 16:09



Bu web sitesinde sadece 1 puanınız olabilir, ancak siz ve tarzınızı beğeniyorum. - horseyguy
W / banister katılıyorum; bu harika bir cevap - Christopher Scott
İlginç bilgiler, ama soruya cevap verme - Alexey
Bu, IFF'nin daha önce DavidSeiler'ın yanıtını okuduğu son derece anlayışlı ve faydalı bir yorumdur. - Jazz
Theo gücü burada yükseltilen istisnayı demode ediyor. - New Alexandria


Yehuda Katz, inceliklerini açıklamak için oldukça iyi bir iş çıkardı "Ruby'de Metagramgramlama: Herşey Kendilik Hakkında"


11
2017-12-21 01:38



altyazı veya ... incelik? ;) - horseyguy
doh :) Bunu tespit ettiğiniz için teşekkürler, şimdi düzeltildi. - Pete Hodgson
Aslında sabit değil - Kamil Lelonek