我正在尝试公开一个使用类型别名参数化的类:
trait Tr[T] {
var x: T = _
}
abstract class Foo {
type MyParameter
class SomeClass extends SomeOtherClass with Tr[MyParameter]
}
class Bar extends Foo {
override type MyParameter = Int
val myObj = new SomeClass
myObj.x = 6
}
class Qux extends Foo {
override type MyParameter = String
val myObj = new SomeClass
myObj.x = "hello"
}
这很好。
现在,我要为MyParameter
类型指定一个默认值。像这样:
abstract class Foo {
type MyParameter = String
// ...
}
// ...
class Qux extends Foo {
val myObj = new SomeClass
myObj.x = "hello"
}
但是,如果我这样做,类Bar
将因类型错误而失败-显然,在这一点上,SomeClass
已被固定为String
。
该如何解决?或者,我可以采取什么其他方法使SomeClass
由具有默认类型的参数进行参数化,但是可以在Foo
的子类中进行覆盖?
请注意,SomeClass
比显示的要复杂,因此我不希望用户必须重写SomeClass
的定义。另外,对X.SomeClass
的所有使用都应使用相同的Tr[T]
,所以我不想使SomeClass
本身可参数化。
答案 0 :(得分:1)
如果您省略分配,则可以找到问题的根本原因:
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait T[T] {
var x: T = _
}
abstract class Foo {
type Param = String
class Child extends T[Param]
}
class Bar extends Foo {
(new Child).x = "foo"
}
class Qux extends Foo {
override type Param = Int
}
// Exiting paste mode, now interpreting.
<pastie>:26: error: overriding type Param in class Foo, which equals String;
type Param has incompatible type
override type Param = Int
覆盖类型遵循与覆盖def
,val
或var
相同的规则:覆盖类型必须与其所覆盖的类型兼容。
例如,您无法重写toString
来返回Int
的方法。
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Test {
override def toString: Int = 1
}
// Exiting paste mode, now interpreting.
<pastie>:12: error: overriding method toString in class Object of type ()String;
method toString has incompatible type
override def toString: Int = 1
^
我的建议是拆分层次结构,因此当您需要将具有Foo
的{{1}}转换为Tr[String]
时,如果需要其他类型,则可以扩展{{1 }}。