Is it possible in Scala to force the caller to specify a type parameter for a polymorphic method?

后端 未结 4 1797
旧时难觅i
旧时难觅i 2020-12-13 01:22
//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         


        
4条回答
  •  佛祖请我去吃肉
    2020-12-13 01:56

    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.

提交回复
热议问题