Trait允许方法签名中的子类型

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()方法发送恐龙或变形虫,因为它返回(生物,生物)的元组

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

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

EEC*_*LOR 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
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:具有返回类型的具体实例的实现方法