我正在尝试公开一个使用类型别名参数化的类:
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
本身可参数化。
最佳答案
如果您省略分配,您可以找到问题的根本原因:
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
^
我的建议是拆分层次结构,因此当您需要将具有 Tr[String]
的 Foo
转换为 FooString
时,如果您需要其他类型,您可以扩展 Foo
。
关于scala - Scala 中可重写的默认类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56758023/