[英]overridable default type parameter in Scala
I am trying to expose a class parametrized with a type alias: 我试图公开一个使用类型别名参数化的类:
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"
}
This works fine. 这很好用。
Now, what I would like to do is to specify a default value for the MyParameter
type. 现在,我想要做的是为MyParameter
类型指定默认值。 Like this: 像这样:
abstract class Foo {
type MyParameter = String
// ...
}
// ...
class Qux extends Foo {
val myObj = new SomeClass
myObj.x = "hello"
}
If I do this, however, class Bar
will fail with a type error -- apparently, at that point, SomeClass
is already fixed to String
. 但是,如果我这样做,类Bar
将失败并出现类型错误 - 显然,在那时, SomeClass
已经固定为String
。
What can I do to fix this? 我该怎么做才能解决这个问题? Alternately, what other approach can I take to have SomeClass
parametrized by a type that has a default, but can be overriden in subclasses of Foo
? 或者,我可以采取什么其他方法让SomeClass
通过具有默认值的类型进行参数化,但是可以在Foo
子类中重写?
Note that SomeClass
will be more complex than shown, so I don't want the users to have to override the definition of SomeClass
. 请注意, SomeClass
将比显示的更复杂,因此我不希望用户必须覆盖SomeClass
的定义。 Also, all uses of X.SomeClass
should use the same Tr[T]
, so I don't want to make SomeClass
itself parametrizable. 此外, X.SomeClass
所有使用应使用相同的Tr[T]
,因此我不想让SomeClass
本身可参数化。
If you omit the assignment you can get to the root cause of the issue: 如果省略该分配,则可以找到问题的根本原因:
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
Overriding a type follows the same rules as overriding a def
, val
or var
: the overriding type has to be compatible with the type it is overriding. 覆盖类型遵循与覆盖def
, val
或var
相同的规则:覆盖类型必须与覆盖它的类型兼容。
The same way you can't override toString
to return an Int
, for example. 例如,您无法覆盖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
^
My suggestion would be to split the hierarchy, so when you need a Foo
that has a Tr[String]
into a FooString
, and if you need other type you can extend Foo
. 我的建议是分裂的层次,所以当你需要一个Foo
具有Tr[String]
成FooString
,如果你需要其他类型的可以延长Foo
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.