Das ist mit dem Liskov Substitution Principle verwandt: Sie können weaker access privileges in subclass (even for Java) nicht zuordnen. Making var
ein def
macht den Setter def x_= (y: T): Unit
privat (wie @Staix sagte). Also in dem Fall, wenn Seadan Car
hat formalen Typ Car
- es sollte nicht zugegriffen werden, aber der Compiler kann solche Fälle im Allgemeinen nicht finden (nur formale Typen sind in der Kompilierzeit bekannt), so dass Verhalten wie jedes schwächere Privileg deaktiviert ist:
Der Punkt der Substituierbarkeit Prinzip ist das Verhalten sollte nicht nach dem Gießen auf den Supertyp geändert werden.
Auf der anderen Seite, scala nur Getter Teil der Variablen außer Kraft setzen könnte als @ Régis Jean-Gilles sagte, dies ist aber nicht so nahe liegende Lösung, weil intuitiv erwarten Benutzer ein var
nach override def
unveränderlich werden. Und es verletzt tatsächlich Uniform Access Principle, weil Sie Ihre var
als zwei Dienste (Leser und Schreiber) sehen müssen, statt einer ist es wirklich, während UAP-Kompatibilität das Gegenteil erfordert: beide Leser und Schreiber sollten durch eine einheitliche Notation dargestellt werden.
P.S. Eigentlich weist deine Frage auf die Unvollständigkeit der UAP-Kompatibilität von scala hin. Wie gesagt, das Überschreiben von var
's Leser und das Verlassen von Writer wird mit UAP inkonsistent sein - es blockiert die Fähigkeit, var
selbst zu überschreiben (so kann man var nicht auf zwei Arten überschreiben: Rechen- und Speicher-ähnlich), auch wenn Sie können sie aufgrund von LSP nicht überschreiben. Aber auch die aktuelle Lösung von scala ist problematisch. Sie können feststellen, dass Sie:
trait Car { def age: Int = 7; def age_=(a: Int) = {}}
class SeadanCar extends Car { override def age: Int = 5}
aber nicht
// just repeating your example
trait Car { var age: Int = 7 }
class SeadanCar extends Car { override def age: Int = 5}
So Scalas Erbe scheint nicht mit UAP kompatibel zu sein. IMHO, das große Problem ist, dass Leser und Var selbst identische Namen haben - so können Sie sie nicht unterscheiden (beim Definieren, nicht beim Zugriff).Ich würde löst es mit so etwas wie:
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}
Hinweis, dass age_
in meinem vorgeschlagenen Beispiel zwingende sollte führen zu:
scalaxx> (new SeadanCarReadOnly).age //call age_ here
resxx: Int = 5
scalaxx> (new SeadanCarReadOnly).age_
resxx: Int = 5
Nicht wie:
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
Von cource, wie Ansatz sollte Deaktivieren var age
und def age_; def age_=
gleichzeitig deaktivieren:
trait Car2 { var age = 100500 }
class SeadanCarReadOnly extends Car2 {
override var age = 17;
override def age_: Int = 5 //should be compile error here
}
aber das ist schwer zu schnell es in Scala Sprache zu implementieren aufgrund der Abwärtskompatibilität
PS/2 Nur zu erwähnen, in Bezug auf Veränderlichkeit/immutabilty Teil der Frage, auf jeden Fall können Sie dies nicht tun (aufgrund LSP):
trait Car { var age: Int = 32 } //or without initial value
class SedanCar extends Car { override val age = 42 }
Und aufgrund LSP + UAP sollte nicht in der Lage sein, dies zu tun:
trait Car { def age: Int = 7; def age_=(a: Int) = {}}
class SedanCar extends Car { override val age = 42 }
regardl Ess die Tatsache, dass Sie :)
Weil Defs sind nicht veränderbar, sondern Methodendefinitionen. Was willst du machen, wenn du in SedanCar "Alter = 32" machst? –
Ich denke OP's Frage ist völlig in Ordnung. Scala wird oft aus gutem Grund als dem einheitlichen Zugangsprinzip folgend angesehen. Es wäre daher nicht unvernünftig zu sehen, dass die 'age'-var-Definition nichts anderes ist als die Definition eines Paares von Getter- und Setter-Methoden (' age' und 'age_ ='). In diesem Fall sollte ich definitiv 'age' überschreiben können, was nur den Getter überschreiben und den Setzer unverändert lassen würde. –