代码之家  ›  专栏  ›  技术社区  ›  Kristy Welsh

在kotlin[duplicate]中使用接口时获取平台声明冲突

  •  9
  • Kristy Welsh  · 技术社区  · 8 年前

    我正在将Java中的一些类转换为kotlin,在尝试从接口继承时遇到编译错误:

    public open fun get content id():String? public open fun getContentId():字符串?

    界面如下:

    interface Media {
      val contentId: String
    
      val displayRunTime: String
    
      val genres: List<String>
    
      val programId: String
    
      val runTime: String
    
      val type: String
    }
    

    class Airing : Media {
      override val contentId: String? = null
      override val displayRunTime: String? = null
      override val genres: List<String>? = null
      override val programId: String? = null
      override val runTime: String? = null
      override val type: String? = null
    
      override fun getContentId(): String? {
        return contentId
      }
    

    3 回复  |  直到 8 年前
        1
  •  6
  •   hotkey    8 年前

    你不需要申报 override fun getContentId(): String? ,因为 val contentId: String Media 接口已被重写 override val contentId: String? .

    您得到的错误意味着您声明的函数在JVM字节码中与已为 contentId 属性(getter具有相同的签名)。

    内容ID 直接,而在Java中,您可以使用生成的访问器 getContentId() setContentId(...)

    此外,Kotlin不允许重写not null String 具有可为null的属性 String? 第一,因为基本接口的用户希望属性中的值不为null。您应该将重写的属性类型替换为 ,或制作 一串

        2
  •  2
  •   holi-java    8 年前

    T? 包括 T null 反过来 T 是的子集 T .所以你不能覆盖 T

    interface Source { val content: Any }
    
    //                               v--- ERROR: `Any?` is not a subtype of `Any`
    class Image(override val content:Any?) : Source
    

    但是,您可以覆盖 T 子集类型 子类型 ,例如:

    interface Source { val content: Any? }
    
    //                              v--- `Any` is a subset of `Any?`
    class Image(override val content:Any) : Source
    
    // `String` is a subtype of `Any` & `Any?` includes `Any`
    //                               v
    class Text(override val content:String) : Source
    

    那么你的代码应该如下。然而,Kotlin是一个空的安全系统,即使属性是一个 属性:

    class Airing : Media {
       //           v--- ERROR: the property isn't initialized      
       override val contentId: String
       ...
    }
    

    您应该在主构造函数中引入属性,以便客户端代码在将来初始化它们,例如:

    class Airing
    constructor(
            override val contentId: String,
            override val displayRunTime: String,
            override val genres: List<String>,
            override val programId: String,
            override val runTime: String,
            override val type: String
    ) : Media 
    

    您还可以为属性提供一些默认值,例如:

    class Airing : Media {
        override val contentId: String = "<default>"
        override val displayRunTime: String = "<default>"
        override val genres: List<String> = emptyList()
        override val programId: String = "<default>"
        override val runTime: String = "<default>"
        override val type: String = "<default>"
    }
    

    getContentId getter ,因此您应该将其删除。

        3
  •  0
  •   AlexTa    8 年前

    变量声明为 val 就像Java final Optional ?

    interface Media {
        var contentId: String?
        //...
    }