Можно получить то, что вы ищете, но это не просто.Проблема заключается в том, что без явного параметра типа компилятор может только определить, что T
равно Nothing
.В этом случае вы хотите, чтобы find
возвращал что-то типа Node
, , а не типа T
(то есть Nothing
), но в любом другом случае вы хотите найти что-то, возвращающее что-то типаT
.
Если вы хотите, чтобы ваш возвращаемый тип изменялся в зависимости от параметра типа, вы можете использовать технику, аналогичную той, которую я использовал в моем API для поднятия метода .
object Finder {
def find[T <: Node] = new Find[T]
class Find[T <: Node] {
def apply[R](name: String)(implicit e: T ReturnAs R): R =
doFind(name).asInstanceOf[R]
}
sealed class ReturnAs[T, R]
trait DefaultReturns {
implicit def returnAs[T] = new ReturnAs[T, T]
}
object ReturnAs extends DefaultReturns {
implicit object returnNothingAsNode extends ReturnAs[Nothing, Node]
}
}
Здесь метод find
возвращает полиморфный функтор, который при применении к имени возвращает объект типа T
или типа Node
в зависимости от значения ReturnAs
аргумент предоставлен компилятором.Если T
равно Nothing
, компилятор предоставит объект returnNothingAsNode
, а метод apply вернет Node
.В противном случае компилятор предоставит ReturnAs[T, T]
, а метод apply вернет T
.
Отказ от решения Пола в списке рассылки, другая возможность заключается в предоставлении неявного для каждоготипа что "работает".Вместо того, чтобы возвращать Node
, когда параметр type не указан, будет выдана ошибка компиляции:
object Finder {
def find[T : IsOk](name: String): T =
doFind(name).asInstanceOf[T]
class IsOk[T]
object IsOk {
implicit object personIsOk extends IsOk[Person]
implicit object nodeIsOk extends IsOk[Node]
}
}
Конечно, это решение плохо масштабируется.