少し検索しましたが、そのような構造の例を見つけることができませんでした:
Person[P <: Person[P]]
それは私が理解できるように説明されています。
これはどのように解決しますか?私には無限の再帰のように見えますが、その結論は間違っているようです。
少し検索しましたが、そのような構造の例を見つけることができませんでした:
Person[P <: Person[P]]
それは私が理解できるように説明されています。
これはどのように解決しますか?私には無限の再帰のように見えますが、その結論は間違っているようです。
これは自己型と呼ばれることもあり(Scalaの明示的に型指定された自己参照と混同しないでください)、通常、メソッドがレシーバーと同じ型のオブジェクトで機能することを表現するのに十分な強度のメソッドシグネチャを持つために使用されます。
例を見てみましょう。たとえば、別のメソッドを取り、を返すAnimal
ジェネリックメソッドを持つ基本トレイトがあるとします。breed
Animal
Animal
trait Animal {
def breed(a: Animal): Animal
}
わかりましたが、実際に必要なのは、breed
すべての具体的な動物が同じクラスの動物とのみ繁殖し、同じクラスの動物を返すことを表現する方法です。次の実装
class Cow extends Animal {
def breed(c: Cow) = new Cow
}
breed
この署名が一致しないため、できません。引数の型を共変的に変更する必要があるため、オーバーライドもできません。これは禁止されています。
救助のための自己タイプ:
trait Animal[A <: Animal[A]] {
def breed(a: A): A
}
class Cow extends Animal[Cow] {
def breed(c: Cow) = new Cow
}
EECOLORがすでに指摘しているように、その背後にある型理論はF有界量化と呼ばれています。
構造自体はTwitter Scala Schoolで説明されており、F-bounded polymorphism と呼ばれています。
// you define it like this
trait X extends Person[X]
// it then gets expanded to this
trait Person[X extends Person[X]]
この構造は、トレイトが拡張しているオブジェクトの型への参照を持つ必要がある場合に使用されます。Scala 学校の説明では不十分な場合は、インターネットで「F-bounded polymorphism」を検索できます。