6

現在、Cake パターンを使用していくつかの最適化アルゴリズムを実装しています。私はよく名前衝突の問題にぶつかります。例えば:

trait Add[T] { this: Foo[T] =>
  def constant: T
  def plus( t1: T, t2: T ): T
  def add( t: T ) = plus( t, constant )
}

trait Mul[T] { this: Bar[T] =>
  def constant: T
  def times( t1: T, t2: T ): T
  def mul( t: T ) = times( t, constant )
}

trait Operations[T] { this: Add[T] with Mul[T] =>
  def neg( t: T ): T
}

ここで、はと特性のconstant両方で定義されていますが、それらの値は異なる場合があります。名前の前に特性名を付けることもできますが、見苦しく脆いものだと思います ( )。それを行うより良い方法はありますか?AddMuldef mulConstant: T

4

2 に答える 2

7

私の知る限りでは、従来のケーキ パターンには、通常、操作をグループ化するために、1 層のトレイト ネストが含まれます。次に、外側の層は実際の「サービス」(ここでは Add、Mul、Operations) を定義せずに宣言します。

trait AddComponent[T] { this: FooComponent[T] =>
  def addition: Add

  trait Add {
    def constant: T
    def plus( t1: T, t2: T ): T
    def add( t: T ) = plus( t, constant )
  }
}

trait MulComponent[T] { this: BarComponent[T] =>
  def multiplication: Mul

  trait Mul {
    def constant: T
    def times( t1: T, t2: T ): T
    def mul( t: T ) = times( t, constant )
  }
}

trait OperationsComponent[T] { this: Add[T] with Mul[T] =>
  def operations: Operations

  trait Operations {
    def neg( t: T ): T
  }
}

次に、"...Component" トレイトを一緒に混合すると、依存関係が配線されます。

trait IntOperations extends Operation[Int] {
  class IntAdd extends Add { ... }
  class IntMul extends Mul { ... }
}

class MyFooBar extends FooComponent[Int] with BarComponent[Int] with IntOperations {
  lazy val addition = new IntAdd
  lazy val multiplication = new IntMul
  lazy val foo = ...
  lazy val bar = ...
}

これにより、特定の名前空間の問題が解決されますが、(「サービス」定義の) 名前の衝突は従来のケーキ パターンの問題のままです。Daniel Spiewakによるブログ投稿で、一般的にどのように解決できるかを示していますが、解決策には独自の (巨大な) トレードオフが伴います (この講演を参照)。

それが少し役立ったことを願っています。

PS ここでは型パラメーターの代わりに抽象型を使用する方が良いかもしれません

于 2013-05-13T10:41:22.110 に答える
1

これは少し言い方が悪いかもしれませんし、あなたの質問に対する直接的な答えではありませんが、コンストラクターへの依存性注入を単純に行う方が簡単ではないでしょうか? 各共同作業者には独自の名前空間があるため、衝突することはありません。また、クラスのパブリック API にも問題はありません。ただし、DI とケーキのパターンを混在させることは依然として困難です。

于 2013-05-14T17:09:13.870 に答える