3

如何在继承特征中定义的方法中强制执行子类型?我在里面放什么???以下

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) 的元组

我想要实现的两个概念是:

  • 变形虫知道如何与变形虫交配,而恐龙知道如何与恐龙交配。所以让他们弄清楚错综复杂的细节。
  • 恐龙不应该传给变形虫。只有变形虫到变形虫
4

1 回答 1

9

通常使用称为 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]whereX声明它必须是一个Organism[X]. 这意味着只有 anX可以传入,也可以进行 extends 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: implementation method with return type of specific instance

于 2013-04-17T19:56:32.160 回答