我有以下 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 的子类之一的实例描述了某种集合,而 Member<C> 类的实例描述了该集合的特定成员。子类 BigCollection 和 SmallCollection 决定了我们拥有的集合的大小。我的想法是在这里添加更多内容,具体取决于集合的使用难度。
可以想象以下示例
红色可能是 Member< 颜色 > 类型的实例/对象
Persons 可以是 SmallCollection< Persons > 类型的子类型
颜色可以是 BigCollection< 颜色 > 类型的子类型,并且基本上是无限的。这意味着,例如,函数 contains(Member< Color >) 永远不会返回 false,只有 Unsure 或可能 True 如果找到它并在特定超时后抛出异常。
只是为了让您对我正在尝试做的事情有一个基本的了解。
如果我想在编译时和运行时都访问 MyCollection<C> 类型,请注意 JVM 的类型擦除如何迫使我使用递归泛型。
我们可以看到它的类型相当安全。我们知道 mapToOtherDomain 将返回一个 E,它是 MyCollection< D > 的子类型,它与我们输入的函数 (Member< C >) -> Member< E >) 中的 E 类型相同。
现在,如果 MyCollection 的子类可以覆盖函数 mapToOtherCollection,那么大小会反映在函数的静态签名中。函数 f 是一对一的映射,因此如果我们将 A 类型的 smallCollection 映射到 BI,则希望输出是 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() 的输出将是静态不确定的,而不是动态不确定的,那也会很整洁。
谢谢