스칼라에서 (path-) 종속 형식으로 놀고있어 다음과 같은 시나리오에서 우연히 발견되어 좋은 해결책을 찾을 수 없습니다. 종속 유형의 계층 구조를 갖고 싶다고 가정하고 각각이 "owner"객체에 대한 참조를 갖기를 원합니다. 이 "back-reference"가 올바른 "owner"객체에 대한 몇 가지 메소드를 호출 할 수 있기를 바랍니다. 올바른 방법은 무엇입니까?참조 백 (Scala)이있는 종속 형식
다음은 작은 예입니다. 종속 유형이 Inner
인 "기본"형 식 Outer
이 있습니다. 기본 Outer
특성은 종속 형식에서 작동하는 일부 방법 double
을 정의합니다. 또한 값이 Int
인 특정 종속 클래스 ConcreteInner
이있는 특정 클래스 ConcreteOuter
이 있습니다.
trait Outer {
outerSelf =>
trait BaseInner {
val outer: outerSelf.type = outerSelf
def asDependent: outer.Inner // #1
// def asDependent: outerSelf.Inner // #2
}
type Inner <: BaseInner
def double(inner: Inner): Inner
}
class ConcreteOuter extends Outer {
case class ConcreteInner(val v: Int) extends BaseInner {
override def asDependent = this
}
type Inner = ConcreteInner
def createInner(v: Int): Inner = new ConcreteInner(v)
override def double(inner: Inner): Inner = new ConcreteInner(2 * inner.v)
}
지금까지 그렇게 좋았습니다. 이제 내가 어떤 Inner
클래스의 인스턴스 만 가지고 있지만 해당 Outer
-instance가없는 컨텍스트에서 double
메서드를 호출 할 수 있기를 원한다고 가정합니다. 예를 들어, 그냥 다른 (독립) 맥락에서 원래 Outer.double
를 호출하는 다른 double
방법을 만들려고하자
object DepTest extends App {
//def double(inner: Outer#Inner) = inner.outer.double(inner) // #3
def double(inner: Outer#Inner) = inner.outer.double(inner.asDependent) // #4
val c1 = new ConcreteOuter
val i1 = c1.createInner(123)
val d1 = double(i1)
println(d1)
}
이 코드는 컴파일하지만 asDependent
의 매우 추한 해킹을 필요로한다. # 4 행 대신 3 행을 사용하면 코드가 컴파일되지 않습니다. 나는 다음과 같은 방법으로 라인 # 3을 분할하는 경우 I 라인 # 2도 asDependent
해킹 작동을 멈 춥니 다 함께 라인 # 1을 대체하는 경우 코드는 또한 더 이상
def double(inner: Outer#Inner) = {
val outer = inner.outer
outer.double(inner.asDependent)
}
를 컴파일되지 않습니다. 어떻게 든 때로는 컴파일러는 Inner
객체와 outerSelf
일명 "소유자"개체의 outer
필드는 같은 일이라고 알고 때로는하지 않으며이 경우 컴파일러를 설득하는 방법을 명확하지 않다처럼
그래서 그것은 본다 그것들을 똑같은 것으로 인식하지 못합니다.
이 방법을 사용할 수 있습니까? 아니면 내 문제에 대한 완전히 잘못된 접근인가? (분명히 현실 세계에서 DepTest.double
과 같은 상위 수준 기능의 일부 라이브러리를 만들려고합니다.