类型参数中的交叉引用

时间:2017-05-04 14:42:23

标签: kotlin

例如在Java中我可以写:

public abstract class Element<S extends Snapshot> { ... }
public abstract class Snapshot<E extends Element> { ... }

然后,在某处,扩展这些类:

public class SnapshotImpl extends Snapshot<ElementImpl> { ... }
public class ElementImpl extends Element<SnapshotImpl> { ... }

但是当我尝试在Kotlin中实现相同的类层次结构时:

abstract class Element<S : Snapshot> 
abstract class Snapshot<E : Element>

我遇到了以下编译错误:

Error:(6, 28) Kotlin: One type argument expected for class Snapshot<E> defined in model Error:(6, 25) Kotlin: One type argument expected for class Element<S> defined in model

有没有办法在Kotlin中重现相同类型的参数限制?

2 个答案:

答案 0 :(得分:11)

Kotlin没有原始类型,你不能只删除类型参数。

与原始类型类似的一个选项是使用star projections

abstract class Element<S : Snapshot<*>> { /* ... */ }
abstract class Snapshot<E : Element<*>> { /* ... */ }

但是你无法正常使用类型参数泛型成员。

另一个选择是引入这样的相互约束:

abstract class Element<E : Element<E, S>, S : Snapshot<S, E>>() { /* ... */ }
abstract class Snapshot<S : Snapshot<S, E>, E : Element<E, S>>() { /* ... */ }

使用此定义,您可以确定,如果您定义SomeSnapshot: Snapshot<SomeSnapshot, SomeElement>,则类型SomeElement 会知道 SomeSnapshot,因为它被限制为源自Element<SomeElement, SomeSnapshot>

然后实施将是:

class SomeElement : Element<SomeElement, SomeSnapshot>() { /* ... */ }
class SomeSnapshot : Snapshot<SomeSnapshot, SomeElement>() { /* ... */ }

答案 1 :(得分:0)

我最近在设计应用程序的抽象层之一时遇到了这个问题。 hotkey's answer中的第一个选项无法通过“此类型参数违反有限边界限制”(至少对于较新的Kotlin 1.2.71)编译。第二个可以工作,但是可以优化一点。甚至认为它仍然很肿,它也会有所作为,特别是当您有更多类型参数时。这是代码:

abstract class Element<S : Snapshot<*, *>> { /* ... */ }
abstract class Snapshot<E : Element<S>, S : Snapshot<E, S>> { /* ... */ }