Я хотел бы извлечь тип вида и использовать его для определения типа возвращаемого значения функции.
например.
Давайте определим черту Container
.
trait Container[T] {
def contained: T
}
Давайте определим черту Extra
, чтобы мы могли расширить ее из нашего контейнера.
trait Extra[T] {
def extra: T
}
Давайте определим черту ContainerExtractor
как
trait ContainerExtractor[T, C <: Container[T]] {
def extract(container: C): T
}
Теперь пользователи могут реализовать ContainerExtractor
, выполнив
new ContainerExtractor[String, Container[String] with Extra[Int]] {
override def extract(container: Container[String] with Extra[Int]): String = ???
}
Неплохо, хотя пользователь должен объявить тип внутри Container
дважды! [String, Container[String] ... ]
Чтобы решить эту проблему с повторениями, я попытался обойти ее, переопределив Container
и ContainerExtractor
как
trait Container[T] {
def contained: T
final type Contained = T
}
trait ContainerExtractor[C <: Container[_]] {
def extract(container: C): C#Contained
}
Таким образом (я надеялся) пользователи, которые хотят реализовать ContainerExtractor
мог бы написать:
new ContainerExtractor[Container[String] with Extra[Int]] {
override def extract(container: Container[String] with Extra[Int]): String =???
}
Хотя это не удается с:
incompatible type in overriding
def extract(container: Test.Container[String] with Test.Extra[Int]): _$2 (defined in trait ContainerExtractor);
found : (container: Test.Container[String] with Test.Extra[Int])String
required: (container: Test.Container[String] with Test.Extra[Int])_$2
Поскольку компилятор не может сделать вывод, что тип, на который указывает подстановочный знак в C <: Container[_]
, является String
в этой реализации черты.
Любая помощь в том, как избежать того, чтобы пользователь определял тип контейнера дважды при реализации ContainerExtractor
?