编写一个比Java更优雅的可复制接口

我试图编写一个接口,类可以实现,使他们“可复制”,(类型)安全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 } } 

显然这不是那么优雅,可CopyableExample的标题看起来过于复杂。 有没有更好的方式来实现这个Kotlin?

这里试图通过牺牲一些静态类型的安全性来减少通用样板文件:

 interface Copyable { fun createCopy(): Copyable } inline fun <reified T : Copyable> T.copy(): T = createCopy() as T 

我们可以利用扩展函数来获得接收器的通用类型,而不需要递归泛型。 我们使内联的扩展函数来指定类型参数,以便在执行类不返回相同类型的实例时检查类型转换并抛出异常。

这是一个示例用法

 class Example(val a: String) : Copyable { constructor(e: Example) : this(ea) override fun createCopy() = Example(this) } fun main(args: Array<String>) { val copiedExample: Example = Example("a").copy() } 

使用协方差的替代解决方案

根据你的用例,你甚至不需要copy方法是通用的,因为我们可以利用协变性 。 像这样声明你的类型

 interface Copyable { fun copy(): Copyable } class Example(val a: String) : Copyable { constructor(f: Example) : this(fa) override fun copy() = Example(this) } 

正如你所看到的,代码val copiedExample: Example = Example("a").copy()仍然可以编译。 这是因为overriden方法可以返回比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 } 

这个问题的解决方法很简单,就是覆盖子接口中的copy方法:

 interface CopyableIterable<T> : Iterable<T>, Copyable { override fun copy(): CopyableIterable<T> }