//API
class Node
class Person extends Node
object Finder
{
def find[T <: Node](name: String): T = doFind(name).asInstanceOf[T]
}
//Call site (correct)
val per
Miles Sabin posted a really nice solution for this problem on the scala-user mailing list. Define a NotNothing type class as follows:
sealed trait NotNothing[T] { type U }
object NotNothing {
implicit val nothingIsNothing = new NotNothing[Nothing] { type U = Any }
implicit def notNothing[T] = new NotNothing[T] { type U = T }
}
Now you can define your Finder as
object Finder {
def find[T <: Node : NotNothing](name: String): T =
doFind(name).asInstanceOf[T]
}
If you try to invoke Finder.find without a type parameter, you'll get a compile-time error:
error: ambiguous implicit values: both method notNothing in object $iw of type [T]java.lang.Object with NotNothing[T]{type U = T} and value nothingIsNothing in object $iw of type => java.lang.Object with NotNothing[Nothing]{type U = Any} match expected type NotNothing[T] Finder.find("joe")
This solution is far more general than the ones proposed in my other answers. The only drawback I can see is that the compile-time error is pretty opaque, and the @implicitNotFound annotation doesn't help.