2013-05-13 2 views
6

나는 현재 케이크 패턴을 사용하여 몇 가지 최적화 알고리즘을 구현하고 있습니다. 나는 종종 이름 충돌 문제를 쳤다. 예를 들어 :케이크 패턴과 이름 충돌을 피하십시오.

여기
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 모두 AddMul 특성에 정의되어 있지만, 그 값은 다를 수 있습니다. 이름에 접미사 이름을 붙일 수는 있지만 못 생기고 부서지기 쉽습니다 (def mulConstant: T). 그것을하는 더 좋은 방법이 있습니까?

답변

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 
    } 
} 

은 다음, 종속성 유선됩니다

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은 blog post을 사용하여이를 해결할 수있는 방법을 보여 주었지만 솔루션에는 자체적 인 (거대한) 절충안이 있습니다 (this talk 참조).

조금 도움이 되었습니까?

P. 타입 매개 변수 대신 여기 추상적 인 타입을 사용하는 것이 더 낫습니다

+0

답장을 보내 주셔서 감사합니다. 실제로 문제를 해결합니다. 추 신에 관해서는 각 특성에 추상적 인 유형'T'를 정의하면 이름 유형 충돌이 발생합니다 ("구성 요소"수준에서 정의되어야 함). 내가 잘못 ? – paradigmatic

+0

이 특별한 경우에,'T'는 모든 특성에서 동일한 "물건"을 의미하므로, 충돌하지 않을 것입니다. 각각의 형질이 서로 다른 유형의 경계를 가진 T에 기여한다고 할지라도 서로 충돌하지는 않을 것입니다. 유형 경계는 함께 혼합 될 때 서로 다른 형질로부터 수집됩니다. 그들이 정한 범위 내에서 충돌을 일으키지 않는 한, 모든 것이 괜찮습니다 (컴파일러의 경우). 그것이 Daniel Spiewak이 블로그 게시물에 보여준 한 가지입니다. 그럼에도 불구하고 필자는 개인적으로 "컴포넌트"레벨에 추상적 유형을 부여 할 것이고, 2 개의 T는 반드시 2 개의 다른 컴포넌트에서 동일한 것을 의미하지는 않기 때문에 "T"보다 더 기술적 인 이름을 부여 할 것입니다. –

+0

확인. 그러나 여기에서는 유형이 통합되어 있는지 (즉, 모든 유형의 T = Int입니다) 모든 유형이 동일한 'T'를 갖는다는 종속성을 표현해야합니다. 제네릭 형식을 제외하고는이를 달성하는 방법을 알지 못합니다. – paradigmatic

0

이것은 말하기가 유행이 아닐 수도 있습니다. 그리고 질문에 대한 직접적인 대답은 아니지만 단순히 생성자에 의존성 삽입을하는 것이 더 쉽지는 않습니까? 각 공동 작업자는 자체 네임 스페이스가 있으므로 충돌이 발생하지 않습니다. 그리고 클래스의 공개 API에는 문제가 없습니다. 그러나 DI와 케이크 패턴을 혼용하기는 어렵습니다.

관련 문제