为什么有 'by' 用于扩展 class 并在函数定义中具体化
why there is 'by' for the extended class and reified in function define
遇到一个带有 class 和一个函数的示例,并试图理解那里的 koltin 语法,
这个IMeta by dataItem
有什么作用?查看了 https://kotlinlang.org/docs/reference/classes.html#classes 并且没有看到如何在派生的 class
中使用 by
为什么 inline fun <reified T> getDataItem()
中需要 reified
?如果有人可以提供示例来解释 reified
?
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
}
}
(既然你问的是两个问题,我就分开回答)
Kolin中的by
关键字用于委托。委托有两种:
1) Implementation by Delegation(有时称为Class委派)
这允许您实现接口并将对该接口的调用委托给具体对象。如果您想扩展一个接口但不想实现它的每个部分,这将很有帮助。例如,我们可以通过委托给 List
来扩展它,并允许我们的调用者为我们提供 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
}
这允许您做类似的工作,但具有属性。我最喜欢的例子是 lazy
,它可以让你懒惰地定义一个 属性。在您引用 属性 之前,不会创建任何内容,并且会缓存结果以便将来更快地访问。
来自 Kotlin 文档:
val lazyValue: String by lazy {
println("computed!")
"Hello"
}
why the reified
is required in the inline fun <reified T> getDataItem()
? If someone could give a sample to explain the reified?
有一些不错的东西documentation on reified type parameters,但我会尽量把它浓缩一下。
Kotlin 中的 reified
关键字用于绕过 JVM 对泛型使用类型擦除这一事实。这意味着在运行时,每当您引用泛型类型时,JVM 不会 知道实际类型是什么。这只是编译时的事情。所以 T
在你的例子中......JVM 不知道它是什么意思(没有具体化,我会解释)。
您会注意到在您的示例中您还使用了 inline
关键字。这告诉 Kotlin,与其在引用函数时调用它,不如插入函数体 inline
。这在某些情况下可能更有效。所以,如果 Kotlin 已经打算在编译时复制我们函数的主体,为什么不复制 T
代表的 class 呢?这是使用 reified
的地方。这告诉 Kotlin 引用 T
的实际具体类型,并且仅适用于 inline
函数。
如果您要从您的示例中删除 reified
关键字,您会得到一个错误:"Cannot check for instance of erased type: T"。通过具体化这一点,Kotlin 知道实际类型 T
是什么,让我们可以安全地进行这种比较(以及由此产生的智能转换)。
遇到一个带有 class 和一个函数的示例,并试图理解那里的 koltin 语法,
这个
IMeta by dataItem
有什么作用?查看了 https://kotlinlang.org/docs/reference/classes.html#classes 并且没有看到如何在派生的 class 中使用 为什么
inline fun <reified T> getDataItem()
中需要reified
?如果有人可以提供示例来解释reified
?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
}
by
为了参考,把相关的定义复制到这里:
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
}
}
(既然你问的是两个问题,我就分开回答)
Kolin中的by
关键字用于委托。委托有两种:
1) Implementation by Delegation(有时称为Class委派)
这允许您实现接口并将对该接口的调用委托给具体对象。如果您想扩展一个接口但不想实现它的每个部分,这将很有帮助。例如,我们可以通过委托给 List
来扩展它,并允许我们的调用者为我们提供 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
}
这允许您做类似的工作,但具有属性。我最喜欢的例子是 lazy
,它可以让你懒惰地定义一个 属性。在您引用 属性 之前,不会创建任何内容,并且会缓存结果以便将来更快地访问。
来自 Kotlin 文档:
val lazyValue: String by lazy {
println("computed!")
"Hello"
}
why the
reified
is required in theinline fun <reified T> getDataItem()
? If someone could give a sample to explain the reified?
有一些不错的东西documentation on reified type parameters,但我会尽量把它浓缩一下。
Kotlin 中的 reified
关键字用于绕过 JVM 对泛型使用类型擦除这一事实。这意味着在运行时,每当您引用泛型类型时,JVM 不会 知道实际类型是什么。这只是编译时的事情。所以 T
在你的例子中......JVM 不知道它是什么意思(没有具体化,我会解释)。
您会注意到在您的示例中您还使用了 inline
关键字。这告诉 Kotlin,与其在引用函数时调用它,不如插入函数体 inline
。这在某些情况下可能更有效。所以,如果 Kotlin 已经打算在编译时复制我们函数的主体,为什么不复制 T
代表的 class 呢?这是使用 reified
的地方。这告诉 Kotlin 引用 T
的实际具体类型,并且仅适用于 inline
函数。
如果您要从您的示例中删除 reified
关键字,您会得到一个错误:"Cannot check for instance of erased type: T"。通过具体化这一点,Kotlin 知道实际类型 T
是什么,让我们可以安全地进行这种比较(以及由此产生的智能转换)。