scala - 允许方法签名中存在子类型的特征

标签 scala generics types

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

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]。这意味着只能传入一个扩展了 Organism[X]X

为了防止Dinosaur extends Organism[Amoeba],我添加了一个 self 类型 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

关于scala - 允许方法签名中存在子类型的特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16068398/

相关文章:

c++ - DWORD 和 DWORD32 之间的区别

c++ - boost::bind 的返回类型是什么?

javascript - javascript中不同数据类型的内存使用情况

java - 如何在不使用collect函数的情况下有效地将rdd转换为list

Scala Slick 在数据库中创建表

java - 如何检查 scala 类是否可以从 java 类分配

java - 如果不同的 Java 泛型类型参数具有相同的名称,为什么它可以分配不同的类型?

scala - : org. scalamacros:quasiquotes 中冲突的跨版本后缀

java - 使用泛型和接口(interface),返回类型是 Object,而不是 Type

java - EclipseLink + JPA + 通用实体 + SINGLE_TABLE 继承