我是 Kotlin 的新手,我正在尝试编译这段代码但没有成功(这只是我想在真实项目中做的一个例子):
abstract class Builder<T: Any, Y: Any>
class BuilderImpl() : Builder<String, Int>()
abstract class Shape<T: Any>(){
abstract var builder: Builder<T, *>
}
class Circle() : Shape<String>(){
override var builder: Builder<String, Int> = BuilderImpl()
}
我想覆盖 Circle 类中 Shape 类的 builder 属性。 Shape 类只知道 Builder 类的第一个泛型类型。第二个可以是任何类型,所以我为此使用 *。
当我尝试覆盖 Circle 类中的 builder 属性时,编译器会报错消息:
"Var-property type is 'Builder<String, Int>', which is not a type of overriden public abstract var builder: Builder<String, *>".
我也尝试过使用“out Any”之类的东西而不是 *,但没有成功。
我不知道如何编译这段代码。
最佳答案
当您覆盖 var
时属性,编译器强制执行该属性
获取重写属性的值是类型安全的:如果原始属性的类型为
S
, 重写的属性应该返回S
的实例, 即它的类型应该是S
或其子类型(例如,当需要Int
时返回Number
是安全的);设置被覆盖属性的值是类型安全的:如果原始属性的类型为
S
, 重写的属性应该接受S
的对象作为它的值,所以它的类型应该是S
或其某些父类(super class)型(例如,如果我们需要存储一个String
,将其存储为Any
就可以了)
考虑到这两个要求,唯一可以重写的类型 var
属性可以是原始属性类型本身,因为它的子类型和父类(super class)型会违反上述条件之一。例如,重写的属性应该仍然能够存储 Builder<T, *>
。 , 并将其类型指定为 Builder<T, Int>
不是一个选项:
val s: Shape<SomeType> = Circle<SomeType>()
val b: Builder<SomeType, *> = someBuilder
s.builder = b // should be type-safe, but won't be with the override you want to do
因此您根本无法更改 var
的类型当你覆盖它时属性,因为,就 Kotlin 泛型而言,它在 in
中和 out
职位。
但是,您可以尝试以下选项之一:
更改为
val
属性(property)。在这种情况下没有第二个要求,您可以将属性的类型更改为原始属性类型的子类型:abstract class Shape<T: Any>(){ abstract val builder: Builder<T, *> } class Circle() : Shape<String>(){ override var builder: Builder<String, Int> = BuilderImpl() // OK }
添加一个泛型参数并在子类中指定。在这种情况下,您将能够使用
var
,因为Circle
将是特化的子类型Shape<String, Int>
, 不是原始类型Shape<T, R>
:abstract class Shape<T: Any, R: Any>(){ abstract var builder: Builder<T, R> } class Circle() : Shape<String, Int>(){ override var builder: Builder<String, Int> = BuilderImpl() // OK }
关于android - Kotlin 泛型继承问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40366470/