考虑这个简单的二叉树类型:
abstract class BinaryTree[T] {
type Repr <: BinaryTree[T]
def left: Repr
def value: T
def right: Repr
def height: Int
def add(elem: T): Repr =
if ( left.height <= right.height ) copy( left.add( elem ), right)
else copy( left, right.add(elem))
def copy( left: Repr, right: Repr ) : Repr
}
abstract class BinarySearchTree[T] extends BinaryTree[T] {
type Repr <: BinarySearchTree[T]
def ordering: Ordering[T]
override def add(elem: T) =
if ( ordering.equiv( elem, value ) ) this.asInstanceOf[Repr]
else if ( ordering.lt(elem, value) ) copy( left.add( elem ), right )
else copy( left, right.add( elem ) )
}
class ScapegoatTree[T]( val value: T, val left: ScapegoatTree[T], val right: ScapegoatTree[T] )(implicit val ordering: Ordering[T])
extends BinarySearchTree[T] {
type Repr = ScapegoatTree[T]
def add = this /* snip */
def copy( left: ScapegoatTree[T], right: ScapegoatTree[T] ) = new ScapegoatTree( value, left, right )
}
class BalancedBinaryTree[T]( val value: T, val left: BalancedBinaryTree[T], val right: BalancedBinaryTree[T] )(implicit val ordering: Ordering[T])
extends BinarySearchTree[T] {
type Repr = BalancedBinaryTree[T]
def add = this /* snip */
def copy( left: BalancedBinaryTree[T], right: BalancedBinaryTree[T] ) = new BalancedBinaryTree( value, left, right )
}
在Scala-IDE中使用Scala 2.9时,add方法无法编译,因为复制需要Repr
而left.add(elem)
和right.add(elem)
返回Repr#Repr
。据我所知,Repr#Repr
必须始终是Repr
的子类型,因此它应该是安全的。我是否没有考虑过某些案例,或者幸运的是,这类型系统会阻止您做一些应该工作的事情?
另外,有没有什么方法可以改变我的类型定义,所以这是合法的,或者断言编译器Repr#Repr
必须是Repr
的子类型(除了演员,我的意思是)。我仍然习惯了Scala,我不确定我是否完全理解了类型系统。我确实通过编写一个执行强制转换的隐式方法来编译它,但这更像是一种解决方法,而不是解决方案。
提前感谢您的帮助。
编辑:我应该补充一点,在我的实际实现中,我有进一步限制Repr类型的子类,如果这会产生影响。
编辑2:根据要求添加了更多代码。此问题也会出现在BinarySearchTree
类型中,但不会出现在ScapegoatTree
指定Repr
的具体实现中。还有一个基本的BinaryTree
的具体实现,但我试图保持最小化,这样你就不必花费太多不必要的代码。
答案 0 :(得分:1)
尝试使用类型参数而不是抽象类型重写,希望它符合您的需要。
trait BinaryTree[T, Repr <: BinaryTree[T, Repr]] {
def left: Repr
def value: T
def right: Repr
def height: Int
def add(elem: T): Repr =
if ( left.height <= right.height ) copy( left.add( elem ), right)
else copy( left, right.add(elem))
def copy( l: Repr, r: Repr ) : Repr
}
trait BinarySearchTree[T, U<:BinarySearchTree[T,U]] extends BinaryTree[T, U] { self:U =>
def ordering: Ordering[T]
override def add(elem: T) =
if ( ordering.equiv( elem, value ) ) self
else if ( ordering.lt(elem, value) ) copy( left.add( elem ), right )
else copy( left, right.add( elem ) )
}
class ScapegoatTree[T]( val value: T, val left: ScapegoatTree[T], val right: ScapegoatTree[T] )(implicit val ordering: Ordering[T]) extends BinarySearchTree[T, ScapegoatTree[T]] {
override def height = 1
override def copy( left: ScapegoatTree[T], right: ScapegoatTree[T] ) = new ScapegoatTree( value, left, right )
}
class BalancedBinaryTree[T]( val value: T, val left: BalancedBinaryTree[T], val right: BalancedBinaryTree[T] )(implicit val ordering: Ordering[T]) extends BinarySearchTree[T, BalancedBinaryTree[T]]{
override def height = 1
override def copy( left: BalancedBinaryTree[T], right: BalancedBinaryTree[T] ) = new BalancedBinaryTree( value, left, right )
}
根据this question,您正在设置“MyType”问题。