代码之家  ›  专栏  ›  技术社区  ›  lannyf

为什么扩展类中有“by”并在函数定义中具体化

  •  0
  • lannyf  · 技术社区  · 7 年前

    遇到一个带有类和函数的示例,并试图理解其中的koltin语法,

    1. 这是什么意思 IMeta by dataItem 做看着 https://kotlinlang.org/docs/reference/classes.html#classes 不知道如何使用 by 在派生类中

    2. 为什么 reified 在 inline fun <reified T> getDataItem() ? 如果有人能举个例子来解释 具体化 ?

      class DerivedStreamItem(private val dataItem: IMeta, private val dataType: String?) :
          IMeta by dataItem {
      
      override fun getType(): String = dataType ?: dataItem.getType()
      fun getData(): DerivedData? = getDataItem()
      
      private inline fun <reified T> getDataItem(): T? = if (dataItem is T) dataItem else null
      

      }

    为了便于参考,复制了以下相关定义:

    interface IMeta {
        fun getType() : String
        fun getUUIDId() : String
        fun getDataId(): String?
    }
    
    class DerivedData : IMeta {
        override fun getType(): String {
            return ""  // stub
        }
    
        override fun getUUIDId(): String {
            return ""  // stub
        }
    
        override fun getDataId(): String? {
            return ""  // stub
        }
    }
    
    0 回复  |  直到 7 年前
        1
  •  3
  •   Todd    7 年前

    为什么 reified 在 inline fun <reified T> getDataItem() ? 如果有人能给出一个例子来解释具体化的过程?

    有一些好消息 documentation on reified type parameters ,但我会尽量精简一些。

    这个 具体化 Kotlin中的关键字用于绕过JVM对泛型使用类型擦除这一事实。这意味着在运行时,每当您引用泛型类型时,JVM都会 不 知道实际的类型是什么。这只是编译时的事情。因此 T 在你的例子中。。。JVM不知道这意味着什么(没有具体化,我会解释)。

    您会在示例中注意到,您也在使用 inline 关键词。这告诉Kotlin,与其在引用函数时调用函数,不如直接插入函数体 内联 .在某些情况下,这可能更有效。所以,如果Kotlin已经在编译时复制了我们的函数体,为什么不直接复制 T 也代表了什么?这就是 具体化 被使用了。这告诉Kotlin参考实际的混凝土类型 T ,并且只适用于 内联 功能。

    如果你要移除 具体化 关键字从您的示例中,您会得到一个错误:“无法检查已擦除类型的实例:T”。通过具体化,科特林知道实际的类型 T 让我们安全地进行这个比较(以及由此产生的智能投射)。

        2
  •  2
  •   Todd    7 年前

    (既然你问了两个问题,我将分别回答)

    这个 by Kolin中的关键字用于委派。授权有两种:

    1) Implementation by Delegation (有时称为班级代表团)

    这允许您实现一个接口,并将对该接口的调用委托给一个具体对象。如果你想扩展一个接口,但不是实现它的每一个部分,这是很有帮助的。例如,我们可以扩展 List 通过授权给它,并允许我们的调用者给我们一个 列表

    class ExtendedList(someList: List) : List by someList {
       // Override anything from List that you need
       // All other calls that would resolve to the List interface are 
       // delegated to someList   
    }
    

    2) Property Delegation

    这允许您执行类似的工作,但需要使用属性。我最喜欢的例子是 lazy ,它让您可以懒洋洋地定义属性。在引用该属性之前,不会创建任何内容,并且会缓存结果,以便将来更快地访问。

    从Kotlin文档中:

    val lazyValue: String by lazy {
        println("computed!")
        "Hello"
    }
    
    推荐文章