scala - 使用抽象类型而不是参数类型的 F-Bound 多态性?

标签 scala generics types

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

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

class Amoeba extends Organism[Amoeba] {
  def reproduceWith(org:Amoeba) = //..code
}

最佳答案

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

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

trait OrganismSystem {
    type Organism <: OrganismOps

    trait OrganismOps {
        def reproduceWith(org: Organism): Boolean
    }
}

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

现在,如果你想创建这些东西的具体实例,你可以这样做:
object MyOrganismSystem extends OrganismSystem {
    case class Organism(species: String) extends OrganismOps {
        def reproduceWith(org: Organism) = species == org.species
    }
}

如果你想定义在有机体系统上通用的方法,你会让他们接受 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)
        }
}

关于scala - 使用抽象类型而不是参数类型的 F-Bound 多态性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16256965/

相关文章:

c++ - 基本 C++ 程序中的数学错误

scala sum By Key 函数

unit-testing - 如何在 C# 中使用 Microsoft Fakes 在接口(interface)中 stub 通用方法定义

android - 警告 : "integer constant too large for long type" . .. 但它是一个 uint64_t?

c# - 泛型方法和方法重载

c# - 为什么 C# 编译器不认为这种泛型类型推断有歧义?

typescript - 导出模型并在模板上使用

scala - 如何使用scala找到元组值?

scala - 光滑 2.0 : How to convert lifted query results to a case class?

scala - 如何通过 Spark 数据帧使用 FASTLOAD 将数据加载到 Teradata 表中