Tho*_*ook 3 generics templates kotlin
在工作中进行代码审查并遇到了我以前从未见过的模板类型的使用。乍一看,代码似乎不应该编译,因为定义似乎是递归的。我将其归结为最简单的可验证示例:
interface Bar<T>
interface Foo<T: Bar<T>> // Surely this is recursive?
Run Code Online (Sandbox Code Playgroud)
我对模板类型如何工作的理解是:
interface Foo<T>-一个Foo的T,没有任何限制
interface Foo<T : Bar>- a Fooof T,其中T被限制为 aBar
假设我上面说的是真的,那么这对我来说没有意义:
interface Bar<T>- a Barof T, 没有约束T
interface Foo<T: Bar<T>>- a Fooof T,其中T被限制为 aBar<T>
哦哦,如何T定义Bar<T>?。
我们知道T是 a Bar<T>,所以如果我们替换Tin Bar<T>,那么它就是 a Bar<Bar<T>>。
我们还没有解决T的Bar......为了便于讨论,让我们来代替T一次。现在我们已经T成为一个Bar<Bar<Bar<T>>>. 这肯定是无穷大吗?
CRTP(递归有界量化)是一种众所周知的设计习惯用法,它经常用于(除其他外)提供具有某种“自我”类型的通用代码。
这是递归泛型的一个实际示例。
假设您有一个对一组可比较值进行操作的函数。
fun <T> findMax(collection: Collection<T>): T?
Run Code Online (Sandbox Code Playgroud)
理想情况下,我们希望将此函数限制为仅对Comparable值集合进行操作:
fun <T> findMax(collection: Collection<Comparable<T>>): Comparable<T>?
Run Code Online (Sandbox Code Playgroud)
就这样。对?
虽然这会起作用,但您需要对返回值进行强制转换才能执行任何有用的操作,因为它返回的是 aComparable<T>而不是 a T。
现在假设我们尝试:
fun <T : Comparable<T>> findMax(collection: Collection<T>): T?
Run Code Online (Sandbox Code Playgroud)
好多了。这确保:
T 是 ComparableT是,可以媲美自己这同样适用于类和继承。
interface SelfReturner<T : SelfReturner<T>> {
fun getSelf(): T
}
class A : SelfReturner<A> {
override fun getSelf(): A // <--
}
Run Code Online (Sandbox Code Playgroud)
由于返回类型协方差,这可以正常工作,因为A是SelfReturner<A>.
这通常用于允许一个类“知道”它自己的类型,但重要的是要记住它不是万无一失的:
class Impostor : SelfReturner<A> {
override fun getSelf(): A // <-- oops!
}
Run Code Online (Sandbox Code Playgroud)
虽然你对这些泛型的明显递归性是正确的,因为人们确实可以写
fun <T : Comparable<Comparable<Comparable<...>>>> findMax(collection: Collection<T>): T?
Run Code Online (Sandbox Code Playgroud)
这不会永远持续下去,因为在单级递归之后通常会满足条件(例如,我们使用String。它是a Comparable<String>,这就是编译器需要检查的全部内容。)
请注意,与 C++ 等不同,Kotlin 不使用模板。泛型类型信息仅供编译器使用,以确保代码正确性,不会在编译后的代码中保留*(请参阅类型擦除)。
模板实例化将导致创建一个新的完全独立的类型,而泛型类型在运行时都被擦除为同一个(非泛型)类。
* 这并不完全正确;一些通用类型信息可用于反射,这就是类型标记起作用的原因,但它仅在有限的情况下可用。
有趣的事实:维基百科声称这是偶然发现的,
作者 Jan Falkin,他不小心从派生类派生了一个基类
因此,即使对于提出这个概念的人来说,它似乎也同样令人困惑。
是的,没有引用,但我们不要破坏魔法。:)
| 归档时间: |
|
| 查看次数: |
136 次 |
| 最近记录: |