The definition of A
says that every implementation must have a field storing an instance of something implementing B
. This field is var
, meaning that other code can change it.
In your ConcreteA
, you're overriding that to restrict the field to hold only your ConcreteB
.
Now, that's fine for code calling the getter, as it will always get something of type B
.
But it's a problem for code calling the setter. What if they try to set some other implementation of B
? The interface says they can, but your concrete implementation can't. That's why the compiler won't allow your implementation. (That's the Liskov Substitution Principle in action, as the Kotlin guys said.)
There are several approaches you could take to make it compile:
You could use a val
instead of a var
in A
, and not allow anyone else to change the value. (Simple, but probably not what you want.)
You could parameterise A
with the type of value, giving B
as an upper bound. That would let implementations (and subinterfaces) restrict the type to ConcreteB
if they wanted to. (That's a bit more complex, but is very flexible and may be best suited to your needs.)
You could keep the type of the field as B
, and just initialise it to your ConcreteB
(as per Alexey's answer). (However, your ConcreteB
would have to allow for the possibility of other B
implementations being set later on.)