我有以下Kotlin类实现类似于Collections接口的东西或包含多个元素的集合。
abstract class MyCollection<C: MyCollection<C>> {
abstract fun contains(e: Member<C>): Member<CollectionOfBooleanValues>
//Function that determines if a Member<C> is present in this collection.
// Maps to a collection of boolean values (True, False and Unsure)
abstract fun <E: MyCollection<E>> mapToOtherCollection(f: (Member<C>) -> Member<E>): E
//Function that return a collection of the element that are created from
//a mapping of this collection through a function f.
//This could for example be the owners of the things of this collection, provided we
//have a Persons class extends MyCollection. Or a collection of all colors of the things in this collection.
}
abstract class BigCollection<C: BigCollection<C>>: MyCollection<C>() {
override fun contains(e: Member<C>): Member<CollectionOfBooleanValues> = Unsure
abstract override fun <E: MyCollection<E>> mapToOtherCollection(f: (Member<C>) -> Member<E>): E
}
abstract class SmallCollection<C: SmallCollection<C>>(val choices: List<Member<C>>): BigCollection<C>() {
override fun contains(e: Member<C>): Member<CollectionOfBooleanValues> =
if(choices.contains(e))
True
else
False
}
abstract class Persons<D: Persons<D>>: MyCollection<D>() {
override fun contains(e: Member<D>): Member<CollectionOfBooleanValues> {
return True
}
}
abstract class Member<D: MyCollection<D>>(sym: String, val collectionType: D) {
}
object CollectionOfBooleanValues: SmallCollection<CollectionOfBooleanValues>(choices = listOf(True, False, Unsure)){
override fun <E: MyCollection<E>> mapToOtherCollection(f: (Member<CollectionOfBooleanValues>) -> Member<E>): E =
throw RuntimeException("Not implemented");
}
object True: Member<CollectionOfBooleanValues>("true", CollectionOfBooleanValues)
object False: Member<CollectionOfBooleanValues>("false", CollectionOfBooleanValues)
object Unsure: Member<CollectionOfBooleanValues>("unsure", CollectionOfBooleanValues)
因此,MyCollection的一个子类的实例描述了某种类的集合和类的实例&lt; C>描述该集合的特定成员。 子类BigCollection和SmallCollection确定我们拥有的集合大小。我的想法是在这里添加更多内容,具体取决于集合的使用难度。
可以想象以下示例
Red可以是Member&lt;类型的实例/对象。颜色&gt;
人可以是SmallCollection类型的子类型&lt;人员&gt;
Color可以是BigCollection类型的子类型&lt;颜色&gt;并且基本上是无限的。这意味着,例如,函数包含(Member&lt; Color&gt;)永远不会返回false,只有在发现它时才会出现Unsure或True,并在特定超时后抛出异常。
这样你就可以对我尝试做的事情有一个基本的了解。
注意JVM的类型擦除如何强制我使用递归泛型,如果我想访问类型MyCollection&lt; C>在编译时和运行时。
我们可以看到它相当安全。我们知道mapToOtherDomain将返回一个E,它是MyCollection的子类型&lt; D>并且它将与函数中的E相同类型(成员&lt; C&gt;) - &gt;构件&LT; E&gt;)我们投入。
现在,如果MyCollection的子类可以覆盖函数mapToOtherCollection,那么整洁将是如此,以便大小反映在函数的静态签名中。函数f是一对一的映射,所以如果我们将类型A的smallCollection映射到B,我希望输出为B的smallCollection。
我觉得这应该是可能的,特别是因为它几乎可以在Java中使用,而且Kotlin应该是Java的通用类型系统的扩展。我不能让它工作。我希望它覆盖,但仍然限制返回类型(因此也限制输入类型)
我已经玩过这样的方法签名:
abstract class BigCollection<C: BigCollection<C>>: MyCollection<C>() {
abstract override fun <E: BigCollection<E>> mapToOtherCollection(f: (Member<C>) -> Member<E>): E
}
给出了编译器错误,它没有覆盖以前的方法,并且像这样
abstract class MyCollection<C: MyCollection<C>> {
abstract fun <E: MyCollection<E>> mapToOtherCollection(f: (Member<C>) -> Member<E>): MyCollection<E>
}
abstract class BigCollection<C: BigCollection<C>>: MyCollection<C>() {
abstract override fun <E: MyCollection<E>> mapToOtherCollection(f: (Member<C>) -> Member<E>): BigCollection<E>
}
表示Type参数超出范围。
如何限制输入/输出类型以更好地匹配此示例中泛型类的子类?如果编译器知道BigCollection中的contains()的输出将是静态的而不是动态的,那么它也会很简洁。
由于
答案 0 :(得分:0)
很难说这是否有帮助,但是您至少可以将其视为解决方法:
abstract class BigCollection<C: BigCollection<C>>: MyCollection<C>() {
override fun <E: MyCollection<E>> mapToOtherCollection(f: (Member<C>) -> Member<E>): MyCollection<E> {
return this.mapToOtherCollection(f)
}
abstract fun <E: BigCollection<E>> mapToOtherCollection(f: (Member<C>) -> Member<E>): BigCollection<E>
}
这里发生的事情类似于JVM“桥接”方法:我们创建一个具有更具体签名的方法并将其委托给它。