Scala'daki Özellikler “elmas hatasını” nasıl önler?


16

(Not: Başlıca nedenlerden dolayı 'problem' yerine 'hata' kullandım ..;)).

Scala'daki Özellikler hakkında bazı temel okumalar yaptım. Java veya C # 'daki Arayüzlere benzerler, ancak bir yöntemin varsayılan olarak uygulanmasına izin verirler.

Merak ediyordum: Bu, "elmas sorunu" na neden olamaz, bu yüzden birçok dil ilk etapta çoklu kalıtımdan kaçınır mı?

Eğer öyleyse, Scala bunu nasıl ele alıyor?


Araştırmanızı paylaşmak herkese yardımcı olur . Neyi denediğinizi ve neden ihtiyaçlarınızı karşılamadığını bize bildirin. Bu, kendinize yardımcı olmak için zaman ayırdığınızı gösterir, bizi açık cevapları tekrar etmekten kurtarır ve en önemlisi daha spesifik ve ilgili bir cevap almanıza yardımcı olur. Ayrıca bkz. Nasıl
Sorulur

2
@gnat: Bu somut bir sorun sorusu değil kavramsal bir sorudur. "Scala'da bu sınıf var ve bana Elmas Sorunu ile ilgili olabileceğini düşündüğüm problemler veriyorsa, nasıl düzeltebilirim?" yorumunuz uygun olur, ancak soru SO'ya aittir. : P
Mason Wheeler

@MasonWheeler Scala'da da bazı temel okumalar yaptım. Ve ilk önce okuduğum şeyde "elmas" araması bana cevap verdi: "Bir özellik Java arayüz yapısının tüm özelliklerine sahiptir. Ancak özellikler onlara yöntemler uygulayabilir. Ruby'ye aşina iseniz, özellikler benzerdir Birçok özelliği tek bir sınıfa karıştırabilirsiniz. Özellikler yapıcı parametrelerini alamaz, ancak sınıf gibi davranırlar. Bu size elmas problemi olmadan birden fazla mirasa yaklaşan bir şeye sahip olma yeteneği verir ". Bu soruda çaba eksikliği oldukça açık hissediyor
gnat

7
Bu ifadeyi okumak, NASIL sadece bunu yaptığını söylemez.
Michael Brown

Yanıtlar:


22

Elmas problem, yöntemin hangi uygulamanın seçileceğine karar verememesidir. Scala, dil spesifikasyonlarının bir parçası olarak hangi uygulamanın seçileceğini tanımlayarak bunu çözer ( bu Wikipedia makalesinde Scala hakkındaki bölümü okuyun ).

Tabii ki, aynı düzen tanımı sınıf çoklu mirasta da kullanılabilir, o zaman neden özelliklerle uğraşasınız ki?

IMO'nun nedeni yapıcılar. Yapıcıların, düzenli yöntemlerin sahip olmadığı çeşitli sınırlamaları vardır - her nesne için sadece bir kez çağrılabilirler, her yeni nesne için çağrılmaları gerekir ve bir alt sınıf kurucusu, ilk talimat olarak üst öğesinin yapıcısını çağırmalıdır (çoğu dil parametreleri geçirmeniz gerekmiyorsa bunu örtük olarak yapın).

B ve C A ve D miras B ve C miras alırsa ve hem B hem de C yapıcıları A yapıcısını çağırırsa, D yapıcısı A yapıcısını iki kez çağıracaktır. Scala gibi hangi uygulamaların yöntemlerle yapıldığını tanımlamak burada işe yaramayacaktır, çünkü hem B hem de C yapıcıları çağrılmalıdır.

Özellikler bu sorunu önler çünkü kurucuları yoktur.


1
Yapıcıları bir kez ve sadece bir kez çağırmak için C3 doğrusallaştırma kullanmak mümkündür - Python çoklu kalıtım bu şekilde yapar. Başımın üstünde D <B | C <Bir elmas için doğrusallaştırma D -> B -> C -> A. Ayrıca, bir google araması bana Scala özelliklerinin değişken değişkenlere sahip olabileceğini gösterdi, bu yüzden kesinlikle bir orada bir yerde yapıcı? Ama kaputun altında kompozisyon kullanıyorsa (bilmiyorum, asla Scala kullanmadım) B ve C'nin A örneğinde paylaşabileceğini görmek zor değil ...
Doval

... Özellikler, arayüz kalıtımını ve kompozisyonunu + temsilci seçmeyi birleştiren tüm ortak plakayı ifade etmenin çok kısa bir yolu gibi görünüyor, ki bu da davranışı yeniden kullanmanın doğru yoludur.
Doval

@Doval Çok sayıda miras alınan Python'daki inşaatçı deneyimlerim onların kraliyet acısı olmaları. Her kurucu hangi sırayla çağrılacağını bilemez, bu nedenle üst kurucusunun imzasının ne olduğunu bilmez. Genel çözüm, her kurucu için bir grup anahtar kelime argümanı alması ve kullanılmayanları süper kurucusuna aktarmasıdır, ancak bu sözleşmeye uymayan mevcut bir sınıfla çalışmanız gerekiyorsa, güvenli bir şekilde devralınamazsınız. o.
James_pic

Başka bir soru, C ++ neden elmas sorunu için aklı başında politika seçmedi?
kullanıcı

21

Scala, "sürekli doğrusallaştırma" adı verilen bir şeyle elmas probleminden kaçınır. Temel olarak, sağdan sola doğru genişlettiğiniz özelliklerde yöntem uygulamasını arar. Basit bir örnek:

trait Base {
   def op: String
}

trait Foo extends Base {
   override def op = "foo"
}

trait Bar extends Base {
   override def op = "bar"
}

class A extends Foo with Bar
class B extends Bar with Foo

(new A).op
// res0: String = bar

(new B).op
// res1: String = foo

Bunu söyledikten sonra, aradığı özellikler listesi, diğer özellikleri genişletebileceğinden, açıkça verdiğiniz özelliklerden daha fazlasını içerebilir. Burada ayrıntılı bir açıklama verilmiştir: İstiflenebilir modifikasyonlar ve buradaki doğrusallaştırmanın daha eksiksiz bir örneği: Neden çoklu kalıtım değil?

Diğer programlama dillerinde bu davranış bazen "Yöntem çözüm sırası" veya "MRO" olarak da adlandırılır.

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.