具有抽象类型而不是参数类型的F-束缚多态?

RAb*_*ham 3 generics types scala

如何使用抽象类型将以下F-Bound多态转换为代码?

trait Organism[Self <: Organism[Self]] { self: Self =>
  def reproduceWith(org:Self):Boolean
}

class Amoeba extends Organism[Amoeba] {
  def reproduceWith(org:Amoeba) = //..code
}
Run Code Online (Sandbox Code Playgroud)

Owe*_*wen 5

有多种方法可以做到这一点.这是我喜欢的一种方式,类似于"参数化模块"OCaml或Agda.

定义Organism类型时,将其拆分为抽象类型Organism和特征OrganismOps.然后你将这两个包装在一个特征中:

trait OrganismSystem {
    type Organism <: OrganismOps

    trait OrganismOps {
        def reproduceWith(org: Organism): Boolean
    }
}
Run Code Online (Sandbox Code Playgroud)

因为它们被包裹在相同的特性中,OrganismOps所以可以看到Organism类型.

现在,如果你想创建这些东西的具体实例,你会这样做:

object MyOrganismSystem extends OrganismSystem {
    case class Organism(species: String) extends OrganismOps {
        def reproduceWith(org: Organism) = species == org.species
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你想定义在有机体系统上一般运行的方法,你可以让它们OrganismSystem作为参数接受,或者等效地将它们包装在一个带有OrganismSystem作为参数的类中:

class UsesGenericOrganismSystem(system: OrganismSystem) {
    import system._

    def allCompatible(organisms: Traversable[Organism]): Boolean =
        organisms.toSeq.combinations(2) forall {
            case Seq(o1, o2) => o1.reproduceWith(o2)
        }
}
Run Code Online (Sandbox Code Playgroud)