Smalltalk'ta sınıf değişkenleri nerede tanımlanır?

Jan 19 2021

Merak ediyordum, örneğin sınıf için yeni bir sınıf değişkeni MyClasstanımlarsam, tanım MyClassiçinde MyClass classmi yoksa içinde mi olacak ? MyClass classYeni sınıf değişkenini bile biliyor mu ?

Yanıtlar

5 LeandroCaniglia Jan 20 2021 at 00:36

Evet, sınıf değişkenleri sınıf ve meta sınıfla paylaşılır. Ayrıca tüm alt sınıflarla (ve meta sınıflarıyla) paylaşılırlar. Bir sınıf değişkeni, sınıftan daha geniş bir kapsamda paylaşılma fikrini daha iyi iletmek için genellikle büyük harfle yazılır. Sınıf değişkenlerini sınıfta tanımlarsınız (meta sınıfta değil).

Sınıf değişkenleri, meta sınıf düzeyinde tanımlanan örnek değişkenleri olan sınıf örneği değişkenleriyle, yani sınıf nesnesinin örnek değişkenleriyle karıştırılmamalıdır. Bu kavram, basitliğine (veya bu nedenle) rağmen biraz belirsizdir: örnek değişkenleri, örneklerinin şeklini (yuvalarını) tanımlamak için her zaman sınıfta tanımlanır . Bu nedenle, bu tanımı sınıfın sınıfı olan meta sınıfa uygularsak, burada tanımlanan bir örnek değişkeni, (genellikle) yalnızca bir sınıf olan örneklerinin şeklini tanımlar.

Sınıf değişkenlerine geri dönersek, onları sınıfta (inst tarafında) tanımlar ve metasınıfta (yani, sınıf tarafında) başlatırsınız. Bunların örnekler, alt sınıflar, alt sınıflar ve meta sınıflar arasında paylaşılacak (kısmi) küreseller olduğunu ve bu nedenle küresellere uyguladığımız olağan özenle ele alınmaları gerektiğini unutmayın.


Bir açıklama daha

Örnek değişkenlerinin örnekler ve alt örnekler arasında paylaşıldığını söylediğimizde, adlarını (ve nesne yuvalarının belleğindeki konumlarını) kastediyoruz; değerlerini kastetmiyoruz (söz konusu yuvaların içerikleri). Bu nedenle, örneğin sınıf ivar'ı tanımlıyorsa, sınıfın iki örneği Cadı paylaşacaktır , ancak bunların her bir colorörnekteki colordeğerleri bağımsız olacaktır. Başka bir deyişle, paylaşılan şey değer değil, addır.

Sınıf değişkenleriyle paylaşılan, hem ad hem de değerdir. Aslında Associationnesnedir, örneğin Theme -> aThemepaylaşılan şeydir. Sonuç olarak, bir sınıf değişkeninin değerinde yapılan herhangi bir değişiklik tüm referanslarını etkiler. Sınıf örneği değişkenlerinde durum böyle değildir çünkü bunlar, normal örnekler ve alt örneklerden ziyade sınıfı ve alt sınıflarını şekillendirmeleri dışında örnek değişkenlerinden başka bir şey değildirler.


Smalltalk değişkenleri hakkında daha fazla bilgi için bkz. https://stackoverflow.com/a/42460583/4081336

2 aka.nice Jan 20 2021 at 23:59

Leandro'nun cevabının bir tamamlayıcısı olarak, örnek tarafı (sınıf) ve sınıf tarafı (metasınıf) arasında sınıf değişkenlerinin paylaşımını açıklayan ana Squeak uygulamasına özgü yöntemi burada bulabilirsiniz:

Metaclass>>classPool
    "Answer the dictionary of class variables."

    ^thisClass classPool

thisClassMetaclass'ın benzersiz örneği nerede , yani sınıfın kendisi ...

Çoğu Smalltalk lehçesinde benzer uygulama bulma şansı yüksektir.

Derleyici önce değişkeni bir yöntem / blok geçici olarak (methd / blok parametreleri dahil), ardından örnek değişkenleri, sonra paylaşılan değişkenler olarak çözmeye çalışacaktır.

ClassPool yöntemi bu son aşamada derleyici tarafından gönderilir.

Bir Leandro açıkladı, derleyici ya bağlamayı, örnek değişkeni yuvası veya yöntem geçici değişkeni durumunda doğrudan bayt koduna kopyalanacak bir ofset olarak ya da paylaşılan değişken durumu için bir tür İlişkilendirme olarak çözdü, bu ilişki genellikle CompiledMethod değişmezlerine eklenir ve bu değişkenle ilgilenen tüm yöntemler arasında etkin bir şekilde paylaşılır (tüm yöntemler, etkin bir şekilde paylaşılan aynı Assocation nesnesine işaret eder).

Derleyici kısmı çok daha fazla lehçeye özgüdür, Squeak'ta paylaşılan değişkenlerin bağlanmasını çözmek için kullanılan bu yöntemdir:

class>>bindingOf: varName environment: anEnvironment
    "Answer the binding of some variable resolved in the scope of the receiver"
    | aSymbol binding |
    aSymbol := varName asSymbol.

    "First look in local classVar dictionary."
    binding := self classPool bindingOf: aSymbol.
    binding ifNotNil:[^binding].

    "Next look in local shared pools."
    self sharedPools do:[:pool | 
        binding := pool bindingOf: aSymbol.
        binding ifNotNil:[^binding].
    ].

    "Next look into superclass pools"
    superclass ifNotNil: [^ superclass bindingOf: aSymbol environment: anEnvironment].

    "No more superclass... Last look in declared environment."
    ^anEnvironment bindingOf: aSymbol

Bu size Smalltalk'ın en ilginç bölümlerinden birinin IDE'nin içinden uygulamaya girebilmeniz olduğunu hatırlatmak için Smalltalk aslında Smalltalk'ta yazılmıştır!