2010-05-09 3 views
3

스칼라에서 정의 된 일반 트리가 있습니다.Scala에서 기존 데이터 구조 확장

sealed abstract class Tree 
object Tree { 
    case class Node (...) extends Tree 
    case class Leaf (...) extends Tree 
} 

이제 트리의 모든 노드와 잎에 멤버 변수를 추가하고 싶습니다. 확장 키워드를 사용할 수 있습니까? 아니면 [T]를 추가하여 트리 클래스를 수정해야합니까?

업데이트 :
내 질문이 오해 된 것 같습니다. 예제는 다음을 지워야합니다.

이 트리 구조가 필요합니다 (실제로는 좀 더 복잡함). 하나의 상황에서 두 개의 Doubles를 필요로합니다. 다른 문맥에서는 하나의 문자열이 필요합니다. 그리고 또 다른 맥락에서 나는 어떤 (추가) 멤버도없는 순수한 나무가 필요합니다. 그리고 첫 번째 변종은 이되고은 세 번째 변형입니다. 의사 코드 :

DTree extends Tree with Touple2[Double, Double] 
object DTree { 
    case class Node (...) extends Tree.Node with Touple2[Double, Double] 
    case class Leaf (...) extends Tree.Leaf with Touple2[Double, Double] 
} 

STree extends Tree with String 
object DTree { 
    case class Node (...) extends Tree.Node with String 
    case class Leaf (...) extends Tree.Leaf with String 
} 

... 

def f (t : Tree) { ... } 

나는 f는 모든 나무를 처리 할 수 ​​있어야합니다.

답변

0

당신은 항상 트리 노드/잎 사이의 중간 서브 클래스 만들 수 있기 때문에, 트리 클래스를 수정할 필요가 없습니다 : 그러나

 

abstract class ExtraMember[T](member:T) extends Tree 
 

을, 당신은 특성에 혼합하여이를 달성 할 수 추가 멤버를 매개 변수로 전달하려면 노드 및 리프로 이동하십시오.

0

추상 클래스 (특성이되지 않을 수 있습니다) 생성자를 가질 수있다, 그래서 당신은 단지 abstract class Tree의 공통 요소를 넣을 수 있습니다 : 등등

abstract 
class Tree(te1: String, te2: Int) 

case 
class Node(...) 
extends Tree(te1Arg, te2Arg) 

하고 있습니다. 서브 클래스 정의의 extends 절에 기본 클래스 생성자 매개 변수를 제공해야합니다.

+0

Tree 클래스를 수정했습니다. 나는 그것이 많은 장소에서 사용되는 것처럼 피하고 싶습니다. 그리고 나는 한 곳에서만 풍부한 나무가 필요합니다. –

+2

@ Łukasz Lew : 그런 다음이 구별을 포착하고 해당 레벨의 (추상) 클래스 중 하나에 공유 요소를 넣는 역할을하는 상속 구조에 새 레이어를 도입하십시오. –

0

추가하려는 회원이 모든 Tree 개체 (및 하위 클래스)에 대해 유효한 경우 논리적 인 장소는 해당 개체를 Tree 개체 자체에 넣는 것입니다.

여기 두 가지 기술을 사용할 수 있습니다. 다른 사람에 의해 언급 한 바와 같이, 당신은 추상 클래스에서 이러한 생성자 PARAMS을 만들 수 있습니다

sealed abstract class Tree(prop1: String, prop2: Int) 

case class Node(prop1: String, prop2: Int) extends Tree(prop1, prop2) 

당신은 또한 그들이 정기적으로 발스/바르하고 서브 클래스를 전문으로 할 수 있습니다. 여기에 게으른 놈들를 사용

sealed abstract class Tree { 
    def prop1 : String 
    def prop2 : Int 
} 

case class Node(a:String, b:Int) extends Tree { 
    lazy val prop1 = "[" + a + "]" 
    lazy val prop2 = b + 42 
} 

가 쉽게 개체의 초기화 순서를 추론 할 수 그것을 : 그것은 쉽게 단순히 생성자를 통해 그들을 데이지 체인 대신 이러한 속성을 계산 할 수 이것은 틀림없이 더 나은 솔루션입니다 또한 속성이 사용되지 않으면 계산상의 오버 헤드를 피할 수 있습니다. 이것은 Scala의 메소드가 속성에 의해 어떻게 구현 될 수 있는지를 보여줍니다. 이른바 uniform access 원칙입니다. 이 방법을 가지고가는 경우에

, 다음은 특성을 통해 속성을 도입 할 수도 있습니다

sealed abstract class Tree 

trait TreeExtras { 
    def prop1 : String 
    def prop2 : Int 
} 

case class Node(a:String, b:Int) extends Tree with TreeExtras { 
    lazy val prop1 = "[" + a + "]" 
    lazy val prop2 = b + 42 
} 

당신은 또한 적절한 등 자기 유형을 자유롭게 사용한다.

2

올바르게 이해하면 일부 트리 노드에 해당 유형의 필드가있는 유형이 필요합니다. 나는 abstract type이 당신이 찾고있는 것이라고 생각합니다. 그것들은 제네릭과 같지만 하위 분류에 더 적합합니다. 이 같은.

sealed abstract class Tree 

trait TypedTree { 
    type T 
    val value:T 
} 

그런 다음, 당신의 예를 수정할 때, 결과 어떤 :

trait DTree extends TypedTree { 
    type T = Touple2[Double, Double] 
} 
object DTree { 
    case class Node (...) extends Tree.Node with DTree 
    case class Leaf (...) extends Tree.Leaf with DTree 
} 

trait STree extends TypedTree { 
    type T = String 
} 
object DTree { 
    case class Node (...) extends Tree.Node with STree 
    case class Leaf (...) extends Tree.Leaf with STree 
} 

이 간접 수준을 추가합니다. 그러나 나는 당신이 한 단계에서 두 가지가 필요한 무언가를 개념화하고 있다는 느낌을 얻습니다.