While I understand why a var
cannot override a val
in subclass and vice versa, I am unable to understand why does Scala not allow a def
in subclass to override a var
in superclass
class Car {
var age = 32
}
class SedanCar extends Car {
override def age = 54
}
As var
is mutable why not allow a def
to override it? Can anyone please help me in understanding this?
I think you have a problem with the concept. From Scala references:
A variable declaration var x: T is equivalent to declarations of a getter function x and a setter function x_=, defined as follows:
So you are trying to override a getter by "age = 54". But now you do not have any use for the setter.
Hope you get what I mean. I think why people "minus" your question is because you are not thinking in the mindset of Scala here.
That's related to the Liskov Substitution Principle: you can't assign weaker access privileges in subclass (even for Java). Making
var
adef
makes the setterdef x_= (y: T ): Unit
private (as @Staix said). So in case whenSeadan Car
has formal typeCar
- it should not be accessed, but compiler can't find such cases in general (only formal types are known in compile-time), so such behavior is disabled like any weaker privilege:The point of Substitutability Principle is behavior should not be changed after casting to the supertype.
On the other hand, scala could override only getter part of variable as @Régis Jean-Gilles said, but this is not so obvious solution, because intuitively user expects a
var
becoming immutable afteroverride def
. And it's actually violating Uniform Access Principle as you have to see yourvar
as two services (reader and writer) instead of one it really is, while UAP-compatibilty requires the opposite: both reader and writer should be represented by one uniform notation.P.S. Actually your question points to scala's UAP-compatibility incompleteness. As i said, overriding only
var
's reader and leaving writer as is will be inconsistent with UAP - it's blocking ability to overridevar
itself (so you can't override var in both ways: computational and storage-like), even regardless that you already can't override it due to LSP. But current scala's solution is also problematic. You may find that you can:But can't
So scala's inheritance seems not to be compatible with UAP. IMHO, the big problem is that reader and var itself have identical names - so you can't distinguish them (when defining, not accessing). I'd solve it with something like:
Note, that overriding
age_
in my proposed example should lead to:Not like:
Of cource, such approach should disable overriding
var age
anddef age_; def age_=
simultaneously:but this is hard to quickly implement it in Scala language due to backward compatibility
P.S./2 Just to mention, regarding mutability/immutabilty part of the question, you definetely can't do this (due to LSP):
And, due to LSP + UAP, shouldn't be able to do this:
regardless the fact that you can :)