如何在继承的特征中定义的方法中强制执行子类型?我在???中放置了什么?下面
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}
}
我的客户代码将类似于:
object BoozeParty {
def gonuts() = {
val (maleOrganism:Organism,femaleOrganism:Organism) = getOrganisms()
maleOrganism.reproduce(femaleOrganism)
}
}
不管我通过getOrganisms()方法发送恐龙还是变形虫,上面的代码都应该起作用,因为它返回了(Organism,Organism)的元组
我要实现的两个概念是:
变形虫知道如何与变形虫交配,而恐龙知道如何交配
与恐龙。因此,让他们找出复杂的细节。
恐龙不应传递给变形虫。只有变形虫到变形虫
最佳答案
通常使用一种称为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
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
用法是这样的:
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)
如果要对类型(以及更复杂的代码)施加更多限制,可以查看以下答案:Scala: implementing method with return type of concrete instance