简体   繁体   English

Scala中的可覆盖默认类型参数

[英]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. 覆盖类型遵循与覆盖defvalvar相同的规则:覆盖类型必须与覆盖它的类型兼容。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM