What is connected with the Liskov replacement principle : you cannot assign weaker access rights to a subclass (even for Java) . Creating var a def makes setter def x_= (y: T ): Unit private (as pointed out by @Staix). Therefore, if Seadan Car has a formal Car type, it should not be accessed, but the compiler cannot find such cases at all (only formal types are known at compile time), therefore this behavior is disabled, like any weaker privilege:
val car2 = new SeadanCar car.age = 422
The point of the principle of substitutability is behavior that cannot be changed after casting in a supertype.
On the other hand, scala can only redefine part of the getter variable, as @ Régis Jean-Gilles said, but this is not such an obvious solution because intuitively the user expects var become unchanged after override def . And this actually violates the Uniform Access Principle , because you should see that your var as two services (reader and writer), and not one, is true, while UAP compatibility requires the opposite: both the reader and the writer should be represented by one unified notation.
PS Actually, your question indicates incomplete compatibility with scala UAP compatibility. As I said, overriding only reading var and leaving a record like this will not be compatible with UAP is blocking the ability to redefine var (so you cannot redefine var in both directions: computational and memory), even regardless of the fact that you are no longer can override it due to LSP. But the current scala solution is also problematic. You may find that you can:
trait Car { def age: Int = 7; def age_=(a: Int) = {}} class SeadanCar extends Car { override def age: Int = 5}
But can't
So scala inheritance seems incompatible with UAP. IMHO, the big problem is that the reader and var itself have the same names, so you cannot distinguish them (when defining, not when accessing). I would resolve this with something like:
trait Car { def age_: Int = 7; def age_=(a: Int) = {}} class SeadanCarReadOnly extends Car { override def age: Int = 5}
Note that overriding age_ in my suggested example should result in:
scalaxx> (new SeadanCarReadOnly).age //call age_ here resxx: Int = 5 scalaxx> (new SeadanCarReadOnly).age_ resxx: Int = 5
I do not like:
trait Car2 { @BeanProperty var age = 100500 } class SeadanCarReadOnly extends Car2 { override def getAge: Int = 5}
Of course, this approach should turn off the var age and def age_; def age_= def age_; def age_= at the same time:
trait Car2 { var age = 100500 } class SeadanCarReadOnly extends Car2 { override var age = 17; override def age_: Int = 5
but it is difficult to implement in scala due to backward compatibility
PS / 2 Just to mention, regarding the issue of mutability / immutability of the question, you definitely cannot do this (due to LSP):
trait Car { var age: Int = 32 } //or without initial value class SedanCar extends Car { override val age = 42 }
And due to LSP + UAP, this should not be:
trait Car { def age: Int = 7; def age_=(a: Int) = {}} class SedanCar extends Car { override val age = 42 }
no matter what you can :)