Reputation: 497
I currently have a inheritance hierarchy as follows:
abstract class Foo {
protected open var elem: Bar<out Foo>? = null
}
class Baz<T : Foo> : Foo {
override var elem: Bar<out T>? = null
}
However, I'm getting the following error when I try to use this code
Var-property is Bar<out T>?, which is not a type of overriden protected open var elem: Bar<out Foo>? defined in Foo
I've also tried types such as:
abstract class Foo {
protected open var elem: Bar<*>? = null
}
class Baz<T : Foo> : Foo {
override var elem: Bar<out T>? = null
}
As well as:
abstract class Foo {
protected open var elem: Bar<Foo>? = null
}
class Baz<T : Foo> : Foo {
override var elem: Bar<T>? = null
}
However, in each of these cases, I still get similar error messages. I know in Java you can override an inherited variable with a more specific generic type. I'm not very familiar with Kotlin and only recently learned about declaration-site variance, so could someone explain what's going on here?
Upvotes: 1
Views: 514
Reputation: 1877
Defining a more specific type for a mutable property would break inheritance and polymorphism rules. For example assume this would compile:
class A
class B : A
abstract class Foo {
protected open var elem: Bar<out A>? = null
}
class Baz : Foo {
override var elem: Bar<out B>? = null
}
Then we have
val foo: Foo = Baz()
val producerOfA: Bar<out A> = foo.elem
This is correct, the variable expects a producer of A
and gets one (the specified type is Bar<out A>
and the actual type is Bar<out B>
, which is a subtype)
With the same declarations:
foo.elem = Bar<out A>()
This is incorrect, the setter expects a producer of A
and gets one, but the underlying type for object foo
is Baz()
which accepts only producers of B
(Bar<out B>
), and of course a producer of A
is not always a producer of B
.
Hope this clears out the issue. You could make it compile by declaring immutable properties (put val
instead of var
), but this is use case specific.
Upvotes: 1