I just started to explore the language Kotlin. I'm struggling with inheritance, var&val and side-effects.
If I declare a trait A
with a val x
and override x
in AImpl
it is possible to override it as var
(see code below). Surprisingly the print()
method in A
is affected by the reassignment of x
even though x
is a value in A
. Is this a bug or a feature?
Code:
trait A {
fun print() {
println("A.x = $x")
}
val x : Int;
}
class AImpl(x : Int) : A {
override var x = x; // seems like x can be overriden as `var`
}
fun main(args: Array<String>) {
val a = AImpl(2)
a.print() // A.x = 2
a.x = 3; // x can be changed
// even though print() is defined in trait A
// where x is val it prints x = 3
a.print() // A.x = 3
}
I'm aware of the fact that if I define a
with type A
explicitly it is not allowed to change x
:
val a = AImpl(2) : A
a.x = 3 // ERROR: value x cannot be reassigned
But as the first case shows, inheritance can cause side effects which are clearly not intended in A
. How do I protect values from being changed by inheritance?
VAL(Value) The object stored using val cannot be changed, it cannot be reassigned, it is just like the final keyword in java. val is immutable.
To override a method of the base class in the derived class, we use the override keyword followed by the fun keyword and the method name to be overridden.
In any object-oriented programming language, Overriding is a feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its super-classes or parent classes.
You can make your val
final
, i.e. forbid overriding it at all.
If you define a val
in a class, it is final
by default.
Also, if you need to override a val
with a var
, but do not want the setter to be public, you can say so:
override var x = 1
private set
Overriding a val
with a var
is a feature. It is equivalent to adding a set-method while in the superclass there was only a get-method. And this is rather important in implementing some patterns, such as read-only interfaces.
There's no way to "protect" your val
from being overridden in a way that allows changing mutation other than making it final
, because val
does not mean "immutable reference", but merely "read-only property". In other words, when your trait A
declares a val
, it means that through a reference of type A
the client can not write this val
, no other guarantees intended, or indeed possible.
P.S. Semicolons are optional in Kotlin, feel free to omit them altogether
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