android - Kotlin 泛型继承问题

标签 android generics kotlin

我是 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/

相关文章:

java - 在Android上读取jpeg文件的量化表

android - 如何转换 "yyyy-MM-dd' T'HH :mm:ssZZZZZ"to "yyyy-MM-dd" without add one day in Android?

android - 为所有屏幕统一设计 Assets

java - 有没有办法在 Android Studio 中以编程方式对线性布局进行排序?

android - 初始化项目时的“java.lang.NoSuchFieldError: ConstraintLayout_Layout_layoutDescription”

java - 将类作为参数传递的泛型方法

使用 java 8 默认方法和实用程序类的 Java 通用枚举功能

android - StopSelf 不会停止我的服务

java - 显式调用泛型方法

java - 如何在java类中使用Kotlin类?