RAb*_*ham 3 generics types scala
如何在继承的特征中定义的方法中强制执行子类型?我把什么放在??? 下面
trait Organism {
def reproduce(org:???):Bool
}
class Amoeba extends Organism {
def reproduce(org:Amoeba) = {// so cute..}
}
class Dinosaur extends Organism {
def reproduce(org:Dinosaur) = { // so scary}
}
Run Code Online (Sandbox Code Playgroud)
我的客户代码将类似于:
object BoozeParty {
def gonuts() = {
val (maleOrganism:Organism,femaleOrganism:Organism) = getOrganisms()
maleOrganism.reproduce(femaleOrganism)
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码应该工作,无论我通过getOrganisms()方法发送恐龙或变形虫,因为它返回(生物,生物)的元组
我想要实现的两个概念是:
使用称为F-有界多态的东西很常见(参见Scala School).
trait Organism[Self <: Organism[Self]] { self: Self =>
def reproduceWith(org:Self):Boolean
}
class Amoeba extends Organism[Amoeba] {
def reproduceWith(org:Amoeba) = ???
}
class Dinosaur extends Organism[Dinosaur] {
def reproduceWith(org:Dinosaur) = ???
}
class Monster extends Dinosaur
Run Code Online (Sandbox Code Playgroud)
Organism[X]在哪里X说它必须是一个Organism[X].这意味着只有一个X可以传入,也可以延伸Organism[X].
为了防止Dinosaur extends Organism[Amoeba]我添加了一个self: Self =>告诉编译器的自我类型,这个特性应该与传入的类型混合在一起.
该mate功能现在看起来像这样:
def mate[Species <: Organism[Species]](male:Species, female:Species) =
male reproduceWith female
Run Code Online (Sandbox Code Playgroud)
用法是这样的:
val a1 = new Amoeba
val a2 = new Amoeba
val d1 = new Dinosaur
val d2 = new Monster
mate(a1, a2)
mate(d1, d2)
// wont compile
// mate(a1, d1)
Run Code Online (Sandbox Code Playgroud)
如果你想要更多的类型限制(以及更复杂的代码),你可以看看这个答案:Scala:具有返回类型的具体实例的实现方法