2014-12-23 19 views
5

bir var alt sınıf ve tersi bir val geçersiz kılamaz anlıyorum, ben Scala var gibi üst sınıfScala'da `var` ile` var` geçersiz kılma imkansız mı?

class Car { 
    var age = 32 
} 

class SedanCar extends Car { 
    override def age = 54 
} 

bir var geçersiz kılmak alt sınıfta def izin vermez anlamak mümkün niçin kesilebilir edilir duyuyorum def'un geçersiz kılmasına izin verilmiyor mu? Bunu anlamada bana yardımcı olan var mı?

+1

Tanılar, dönüştürülebilir varaibles değil, yöntem tanımları olduğundan. SedanCar'da yaş = 32’yi yaparsanız ne yapmak istersiniz? –

+5

Bence OP'nin sorusu tamamen mantıklı. Scala genellikle iyi bir sebepten dolayı tek tip erişim ilkesine bağlı olarak sunulur. Daha sonra, 'yaş' var tanımını, bir çift getter ve ayarlayıcı ('age' ve age_ =') yönteminin tanımından başka bir şey olarak görmemek mantıksız olmaz. Bu durumda, aslında yalnızca alıcıyı geçersiz kılacak ve ayarlayıcıyı olduğu gibi bırakacak olan 'yaşı' kesinlikle geçersiz kılmalıyım. –

cevap

12

Bu, Liskov Substitution Principle ile ilgilidir: weaker access privileges in subclass (even for Java)'u atayamazsınız. var değerini def yapmak, ayarlayıcıyı def x_= (y: T): Unit özel olarak yapar (@Staix'in dediği gibi). Yani, Seadan Car, Car resmi türüne sahip olduğunda - erişilmemelidir, ancak derleyici genel olarak bu tür durumları bulamamaktadır (yalnızca resmi türler derleme zamanında bilinir), böylece bu tür davranışlar daha zayıf bir ayrıcalık gibi devre dışı bırakılır:

val car2 = new SeadanCar 

car.age = 422 //compiler error, can't mutate "def age" 

val car: Car = new SeadanCar 

car.age = 42 //now you had mutated immutable 

Değiştirilebilirlik Prensibi, davranış, üst düzeyine döktükten sonra değiştirilmemelidir. Öte yandan

, scala Régis Jean-Gilles söyledi @ gibi değişkenin sadece gaz giderici kısmını geçersiz olabilir, ama sezgisel olarak kullanıcı var override def sonra değişmez hale bekler çünkü bu, çok açık bir çözüm değildir. Ve aslında var'unuzu var'u görmeniz gereken gibi iki hizmet (okuyucu ve yazar) olarak görmeniz, UAP-uyumluluğun tam tersini gerektiriyorken, hem okuyucu hem de yazarın tek bir notasyon ile temsil edilmesi gerekir.

P.S. Asıl soru, scala'nın UAP uyumluluk eksikliğine işaret ediyor. Dediğim gibi, sadece var 'un okuyucusu ve yazarı olduğu gibi bırakarak UAP ile tutarsız olacak - bu, var'u geçersiz kılma özelliğini engelliyor (böylece varlıkları her iki şekilde de geçersiz kılabilirsiniz: hesaplama ve depolama gibi) LSP nedeniyle zaten geçersiz kılabilirsiniz. Ama şu anki scala'nın çözümü de sorunlu.

trait Car { def age: Int = 7; def age_=(a: Int) = {}} 

class SeadanCar extends Car { override def age: Int = 5} 

Ama yapamam

// just repeating your example 

trait Car { var age: Int = 7 } 

class SeadanCar extends Car { override def age: Int = 5} 

Yani Scala'nın miras UAP ile uyumlu olacak şekilde değil görünüyor: Eğer mümkün olduğunu görebilirsiniz. IMHO, en büyük sorun, okuyucu ve var'ın kendisinin de aynı isimlere sahip olması. Bu yüzden onları ayırt edemezsiniz (tanımlarken, erişemediğinizde).

scalaxx> (new SeadanCarReadOnly).age //call age_ here 
resxx: Int = 5 

scalaxx> (new SeadanCarReadOnly).age_ 
resxx: Int = 5 

gibi değil: benim önerilen örnekte age_ geçersiz kılma gitmelidir ki

trait Car { def age_: Int = 7; def age_=(a: Int) = {}} 
class SeadanCarReadOnly extends Car { override def age: Int = 5} //can't compile as reader is closed 
class SeadanCarVar extends Car { override var age: Int = 5} 
class SeadanCarReadOnly extends Car { override def age_: Int = 5} 

trait Car2 { var age = 100500 } 
class SeadanCarReadOnly extends Car2 { override def age_: Int = 5} 

Not: Ben gibi bir şeyle bunu çözmek istiyorum Cource

trait Car2 { @BeanProperty var age = 100500 } 
class SeadanCarReadOnly extends Car2 { override def getAge: Int = 5} 

//which leads to inconsistency: 

scala> (new SedanCar()).age 
res6: Int = 30 

scala> (new SedanCar()).getAge 
res7: Int = 54 

, böyle yaklaşım var age ve def age_; def age_='u aynı anda geçersiz kılmayı devre dışı bırakmalıdır:

trait Car2 { var age = 100500 } 
class SeadanCarReadOnly extends Car2 { 
    override var age = 17; 
    override def age_: Int = 5 //should be compile error here 
} 

ancak bu durum söz konusu değişebilirlik/immutabilty kısmı ile ilgili olarak

PS/2 Sadece söz geriye dönük uyumluluk, hızla Scala dilinde bunu uygulamaya zordur, definetely (bunu yapamaz nedeniyle) LSPye:

trait Car { def age: Int = 7; def age_=(a: Int) = {}} 
class SedanCar extends Car { override val age = 42 } 

regardl:

trait Car { var age: Int = 32 } //or without initial value 
class SedanCar extends Car { override val age = 42 } 

Ve nedeniyle LSP + UAP için, bunu yapmak mümkün olmamalı Bu gerçeği sizin için :)

+1

"Hangi kullanıcıların beklediği" bölümünü satın alabilirim, ancak yalnızca alıcıyı geçersiz kılan UAP'yi ihlal edeceğine saygı duyuyorum. Sonuçta, bunu yaparken de sadece 'yaşını' referans alarak 'yaş' okuyabilir veya yazabilirsiniz. "Tekdüze bir gösterimin" nasıl daha fazla olabileceğini anlamıyorum. Bu sınırlamanın nedenlerini hayal edebilirim, fakat UAP'ı kırmak bunlardan biri değil, tam tersi. –

+0

Bir yan not olarak, aslında alıcıyı tek başına geçersiz kılmayacak kadar önemsemiyorum. Ama aslında bir var olanı geçersiz kılmazsın ve birinin bir bummer olduğunu. –

+0

1) 'var' tekdüze bir göstergedir,' get' + 'set' değildir. "Hadi sadece geçersiz kılmayalım" derken - Belli ki ikinciyi tercih ediyorsunuz ve kullanıcıyı getters/setter'ları düşünmeye itiyorsunuz. 2) Örneğimdeki örneğimin, neden "hiç" yi geçersiz kılma nedenini görecek kadar açık olduğunu düşünüyorum. – dk14

0

Kavramla ilgili bir probleminiz olduğunu düşünüyorum. Scala referanslardan:

Bir değişken bildirimi var x:

def x: T 
def x_= (y: T): Unit 
Yani

geçersiz kılmak çalışıyoruz şu şekildedir: T ned bir alıcı fonksiyonu x ve ayarlayıcı fonksiyonu X_ =, de fi açıklamalarına eşdeğerdir "yaş = 54" ile bir alıcı. Ama şimdi setter için herhangi bir kullanımınız yok.

Ne demek istediğimi umarım. Bence insanlar neden "eksi" diye soruyorlar çünkü burada Scala'nın zihniyetinde düşünmüyorsun.

+4

Cevabınız, sorunun özünü tam olarak gösterir: 'var x: T', x'e karşılık gelir: x; def x_ = (y: T): Birim ', ama değil. İkinci tanımla, yalnızca alıcıyı geçersiz kılmaya ve setleyiciyi olduğu gibi bırakmaya tamamen hakkım vardır. Bu var tanımında doğru değil. –

+3

Hahahahaha, başka bir Scala belirtim hatası. Temiz! – gzm0

+0

@ RégisJean-Gilles bir beyan tanımı değildir. –