返回类在Scala中扩展通用特征

时间:2017-07-22 04:23:12

标签: scala generics scala-generics

Scala代码:

trait Converter[S, T] {
  def convert(source: S): T
}

class StringDuplicatorConverter extends Converter[Integer, String] {
  override def convert(source: Integer): String = {
    source.toString + source.toString
  }
}

// whatever, the point is to show potentially many 'converters'
// from Integer (for example) to something
class SomeOtherConverter extends Converter[Integer, User] {
  override def convert(source: Integer): User = {
    User(source)
  }
}

trait ConverterProvider {
  def getConverter[N]: Converter[Integer, N]
}

class MyClass extends ConverterProvider {
  override def getConverter[N]: Converter[Integer, N] = {
    new StringDuplicatorConverter()
  }
}

给出

Error:(17, 5) type mismatch;
 found   : StringDuplicatorConverter
 required: Converter[Integer,N]
    new StringDuplicatorConverter()

2 个答案:

答案 0 :(得分:1)

是。对getConverter[N]的调用应返回Converter[Integer,N]类型的内容,但StringDuplicatorConverter类型为Converter[Integer,String]。由于N不限于String,因此它们是不同的类型,因此无法编译。

如果编译器得到了NString的超级类型或trait Converter[S, +T] { ... 的超类型的保证,那么它将起作用。这可以通过使返回类型协变来完成......

getConverter

...然后定义def getConverter[N >: String]: Converter[Integer, N] 和覆盖,如下所示:

val mc = new MyClass
mc.getConverter.convert(7)  // res0: String = 77

现在它编译并且似乎有效。

{{1}}

答案 1 :(得分:1)

可能是你真正想要的是为每个ConverterProvider提供转换器到特定类型(否则MyClass的定义没有多大意义:它应为不同的N返回不同的转换器,而不是StringDuplicatorConverter)。如果是这样,正确的定义是

trait ConverterProvider[N] {
  def getConverter: Converter[Integer, N]
}

class MyClass extends ConverterProvider[String] {
  override def getConverter: Converter[Integer, String] = {
    new StringDuplicatorConverter()
  }
}