Tod*_*ell 5 generics copy interface self-type kotlin
我正在尝试编写一个类可以实现的接口,使它们"可复制",一个(类型)安全的Clonable.
在Java中,我会使用递归泛型做类似的事情:
public interface Copyable<C extends Copyable<C>> {
C copy();
}
public class Example implements Copyable<Example> {
...
@Override
public Example copy()
{
return new Example(this); //invoke copy constructor
}
}
Run Code Online (Sandbox Code Playgroud)
显然,这不是那么优雅,标题Copyable和Example看起来过于复杂.在Kotlin有更优雅的方式来实现这一目标吗?
这是尝试通过牺牲一些静态类型安全来减少通用样板:
interface Copyable {
fun createCopy(): Copyable
}
inline fun <reified T : Copyable> T.copy(): T = createCopy() as T
Run Code Online (Sandbox Code Playgroud)
我们可以利用扩展函数来获得接收器的泛型类型,而无需递归泛型.我们使扩展函数内联以重新定义类型参数,以便在实现类不返回相同类型的实例时检查强制转换并抛出异常.
这是一个示例用法
class Example(val a: String) : Copyable {
constructor(e: Example) : this(e.a)
override fun createCopy() = Example(this)
}
fun main(args: Array<String>) {
val copiedExample: Example = Example("a").copy()
}
Run Code Online (Sandbox Code Playgroud)
根据您的使用情况,您甚至不需要该copy方法是通用的,因为我们可以利用协方差.像这样声明你的类型
interface Copyable {
fun copy(): Copyable
}
class Example(val a: String) : Copyable {
constructor(f: Example) : this(f.a)
override fun copy() = Example(this)
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,代码val copiedExample: Example = Example("a").copy()仍然可以编译.这是因为override方法可以返回比super方法更具体的类型,并且使用Kotlin的单表达式函数可以自动推断出我们想要的类型.
但是,如果您不直接使用特定类型,但可以说是子接口,则会导致问题Copyable.以下代码无法编译:
interface CopyableIterable<T> : Iterable<T>, Copyable
class Example : CopyableIterable<String> {
constructor(e: Example)
override fun copy() = Example(this)
override fun iterator() = TODO()
}
fun foo(ci: CopyableIterable<String>) {
val copy: CopyableIterable<String> = ci.copy() // error: type mismatch
}
Run Code Online (Sandbox Code Playgroud)
对此的修复很简单,也可以覆盖copy子接口中的方法:
interface CopyableIterable<T> : Iterable<T>, Copyable {
override fun copy(): CopyableIterable<T>
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
888 次 |
| 最近记录: |