A özelliği B'yi uzatırsa, A'ya karıştırmak size tam olarak B artı A'nın eklediği veya genişlettiği her şeyi verir . Özellik bir açıkça B olarak yazıldığında kendinden referansı varsa aksine, daha sonra nihai ana sınıfı da B'de karıştırmak gerekir veya B soyundan türü (ve bunu karıştırmak ilk önemli olduğu,).
En önemli fark bu. İlk durumda, kesin B tipi, A noktasında onu genişletir. İkincisi, ana sınıfın tasarımcısı, ana sınıfın oluşturulduğu noktada B'nin hangi sürümünün kullanılacağına karar verir.
Başka bir fark, A ve B'nin aynı isimde yöntemler sağlamasıdır. A'nın B'yi uzatması durumunda, A yöntemi B'leri geçersiz kılar. A'nın B'den sonra karıştığı yerlerde, A yöntemi basitçe kazanır.
Yazılan öz referans size çok daha fazla özgürlük verir; A ve B arasındaki bağlantı gevşek.
GÜNCELLEME:
Bu farklılıkların yararı hakkında net olmadığınız için ...
Doğrudan miras kullanıyorsanız, B + A olan A özelliğini yaratırsınız. İlişkiyi taş olarak belirlediniz.
Yazdığınız bir öz referans kullanıyorsanız, A özelliğinizi C sınıfında kullanmak isteyen herkes
- B'yi ve ardından A'yı C'ye karıştırın.
- B ve sonra A alt tipini C'ye karıştırın.
- A'yı C'ye karıştırın, burada C B'nin bir alt sınıfıdır.
Ve bu, Scala'nın yapıcı olarak bir kod bloğu ile doğrudan bir özelliği başlatmanıza izin verdiği şekilde, seçeneklerinin sınırı değildir.
A'nın kazanma yöntemi arasındaki farka gelince , A, A genişletme B'ye kıyasla son olarak karıştırıldığı için bunu düşünün ...
Bir dizi özellikte karıştırdığınızda, yöntem foo()
her çağrıldığında, derleyici aramak için karıştırılan son özelliğe gider foo()
, daha sonra (bulunamazsa), diziyi uygulayan foo()
ve kullanan bir özellik bulana kadar sola doğru hareket eder. söyledi. A, arama yapma seçeneğine de sahiptir super.foo()
, bu da bir uygulama bulana kadar diziyi sola doğru hareket ettirir, vb.
Yani A'nın B'ye yazdığı bir öz referansı varsa ve A'nın yazarı B'nin uyguladığını bilirse foo()
, A super.foo()
başka bir şey sağlamazsa foo()
B'nin bileceğini söyleyebilir . Bununla birlikte, C sınıfının yaratıcısı, uygulandığı diğer özellikleri bırakma seçeneğine sahiptir ve foo()
bunun yerine A bunu alır.
Yine, bu A genişleyen B'den çok daha güçlü ve daha az sınırlayıcıdır ve doğrudan B'nin sürümünü çağırır foo()
.