"几乎是"斯卡拉的关系

duc*_*thd 1 scala mixins

我正在尝试设计一个类层次结构,其中包含一堆类似的类,这些类并不完全共享"是一种"关系.我们称之为这些Model课程.这些类旨在与类似算法的集合配对,这些算法使用Model类但不具有相同的要求.我们称之为这些Strategy课程.诀窍是Strategy类需要从类中获得许多相同的东西Model,但并非所有Model类都能够实现那些所需的方法.我希望没有空的"存根"方法只会抛出UnsupportedOperationExceptions,而是采用类型安全的基于mixin的方式来处理这个问题 - 我可以应用一种设计模式吗?

例如,

object Main extends App {
    trait A {
        def f(one: Int): Int
        def g(two: Int): Int
        def h(three: Int): Int
    }

    class A1 extends A {
        override def f(one: Int): Int = {one + 1}
        override def g(two: Int): Int = {two + 2}
        override def h(three: Int): Int = {assert(false); 0}
    }

    class A2 extends A {
        override def f(one: Int): Int = {assert(false); 0}
        override def g(two: Int): Int = {two - 2}
        override def h(three: Int): Int = {three - 3}
    }

    trait B {
        def combine(i: Int): Int
    }

    trait B1 extends B {
        this: A =>
        override def combine(i: Int) = {f(i) + g(i)}
    }

    trait B2 extends B {
        this: A =>
        override def combine(i: Int) = {g(i) + h(i)}
    }

    override def main(args: Array[String]): Unit = {
        val a11 = new A1 with B1
        val a22 = new A2 with B2

        println(a11.combine(3))
        println(a22.combine(3))

        val a12 = new A1 with B2
        println(a12.combine(3))
    }
}
Run Code Online (Sandbox Code Playgroud)

A是一个Model班级,BStrategy班级.请注意,A1可能无法实现h(),并且A2可能无法实现f(),并且根据策略类,这可能是也可能不是问题.我希望能够找到A的哪个实现可以在编译时使用哪个B实现.

我使用自我类型来表达一种更多的"有一种"而不是"一种"的关系,通常会延伸.

Pet*_*itz 5

我的解决方案:

trait F { def f(one: Int): Int }
trait G { def g(two: Int): Int }
trait H { def h(three: Int): Int }

trait A
trait A1 extends A with F with G {
  def f(one: Int): Int = { one + 1 }
  def g(two: Int): Int = { two + 2 }
}
trait A2 extends A with G with H {
  def g(two: Int): Int = { two - 2 }
  def h(three: Int): Int = { three - 3 }
}

trait B {
  def combine(i: Int): Int
}
trait B1 extends B {
  this: A with F with G =>
  def combine(i: Int) = { f(i) + g(i) }
}
trait B2 extends B {
  this: A with G with H =>
  def combine(i: Int) = { g(i) + h(i) }
}

val a11 = new A1 with B1
val a22 = new A2 with B2

println(a11.combine(3))
println(a22.combine(3))

val a12 = new A1 with B2 // won't compile as you wanted
Run Code Online (Sandbox Code Playgroud)