Collections インターフェースまたは複数の要素を含むセットに似たものを実装する次の Kotlin クラスがあります。
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 のサブクラスの 1 つのインスタンスは、ある種のセットを記述し、クラス Member< C > のインスタンスは、そのコレクションの特定のメンバーを記述します。サブクラス BigCollection と SmallCollection は、コレクションのサイズを決定します。私の考えは、コレクションを扱うのがどれほど難しいかに応じて、ここにさらに追加することです.
次の例を想像することができます
赤はタイプ Member< Color > のインスタンス/オブジェクトである可能性があります
Persons は、型 SmallCollection< Persons > のサブタイプである可能性があります
Color は、タイプ BigCollection< Color > のサブタイプであり、本質的に無限である可能性があります。これは、たとえば、関数 contains(Member< Color >) が false を返すことはできず、Unsure または True を返す可能性があることを意味し、特定のタイムアウト後に例外をスローします。
私がやろうとしていることの基本的な考えをあなたが持っているように。
コンパイル時と実行時の両方で型 MyCollection< C > にアクセスしたい場合、JVM の型消去によって再帰ジェネリックの使用が強制されることに注目してください。
かなり型安全であることがわかります。mapToOtherDomain が MyCollection< D > のサブタイプである E を返すことはわかっています。これは、入れた関数 (Member< C >) -> Member< E >) の E と同じタイプになります。
ここで、MyCollection のサブクラスが関数 mapToOtherCollection をオーバーライドして、サイズが関数の静的シグネチャに反映されるようにできれば、すばらしいことです。関数 f は 1 対 1 のマッピングであるため、タイプ 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 引数が範囲外であることを示しています。
この例のジェネリック クラスのサブクラスによりよく一致するように、in/out 型を制限するにはどうすればよいですか? BigCollection 内の contains() の出力が、動的ではなく静的に Unsure になることをコンパイラが認識していれば、それも素晴らしいことです。
ありがとう