I don't understand. Why does Scala support override method as field:
abstract class A {
def i: Int;
}
class B extends A {
val i = 123;
}
val obj:A = new B();
println(obj.i)
Method i is as field i. Why?
One quick way to see what's going on here is to compile this code and use javap to inspect the resulting classes. Here we get the following for A:
public abstract class A implements scala.ScalaObject {
public abstract int i();
public A();
}
And for B (with -p, so we see any private members):
public class B extends A implements scala.ScalaObject {
private final int i;
public int i();
public B();
}
So the val just ends up as a private field with a getter—much like what you'd write in idiomatic Java, although the naming convention is different (and isn't really a convention, since the compiler handles it for you).
Travis' answer explains how, at the implementation level, some methods can be overridden by a field in Scala but not why. The answer to the why question is related to two programming language design principles: the Uniform Access Principle and the Liskov Substitution Principle.
The Uniform Access Principle essentially says that callers shouldn't have to distinguish between reading a property through a method and reading it through a field -- both calls should look the same and should not betray whether they involve storage or computation.
The Liskov Substitution Principle essentially says that a subtype must honor all the contracts of its parent type. A subtype is allowed to honor stronger contracts than its parent type, but it must not violate any of its parent's contracts.
In Scala, declaring a def without a parameter list implies a certain contract. Namely, it implies that accessing the associated property will return a value of the declared type. Since referential transparency is not guaranteed, subsequent accesses may or may not return the same value.
Clearly, a val satisfies the same contract. However, a val makes an even stronger guarantee: every access will result in the same value. Since this is a stronger contract, it's perfectly consistent with the Liskov Substitution Principle for a subtype to use a val to implement a def. Along the same lines, it's prohibited for a subtype to use a def to implement a val.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With