Возвращаемый класс, расширяющий общую черту в 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 ответа
Это может быть то, что вы действительно хотите для каждого 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()
}
}
Да. Вызов getConverter[N]
должен вернуть что-то типа Converter[Integer,N]
но StringDuplicatorConverter
это тип Converter[Integer,String]
, поскольку N
не ограничивается String
и, следовательно, они разных типов, это не скомпилируется.
Если компилятору дали некоторую гарантию, что N
это, или супер-тип, String
тогда это будет работать. Это можно сделать, сделав возвращаемый тип ковариантным...
trait Converter[S, +T] { ...
... а затем определяя getConverter
и переопределить, вот так:
def getConverter[N >: String]: Converter[Integer, N]
Теперь он компилируется и, кажется, работает.
val mc = new MyClass
mc.getConverter.convert(7) // res0: String = 77