Próbuję utworzyć typeclass Default
, który dostarcza domyślną wartość dla danego typu. Oto co mam wymyślić do tej pory:Niejawna rozdzielczość parametru - ustawienie pierwszeństwa
trait Default[A] {
def value: A
}
object Default {
def withValue[A](a: A) = new Default[A] {
def value = a
}
def default[A : Default]: A = implicitly[Default[A]].value
implicit val forBoolean = withValue(false)
implicit def forNumeric[A : Numeric] =
withValue(implicitly[Numeric[A]].zero)
implicit val forChar = withValue(' ')
implicit val forString = withValue("")
implicit def forOption[A] = withValue(None : Option[A])
implicit def forAnyRef[A >: Null] = withValue(null : A)
}
case class Person(name: String, age: Int)
case class Point(x: Double, y: Double)
object Point {
implicit val pointDefault = Default withValue Point(0.0, 0.0)
}
object Main {
def main(args: Array[String]): Unit = {
import Default.default
println(default[Int])
println(default[BigDecimal])
println(default[Option[String]])
println(default[String])
println(default[Person])
println(default[Point])
}
}
Powyższa implementacja zachowuje się zgodnie z oczekiwaniami, z wyjątkiem przypadków BigInt
i BigDecimal
(i innych typów zdefiniowanych przez użytkownika, które są przypadki Numeric
) gdzie daje null
zamiast zero. Co powinienem zrobić, aby forNumeric
miał pierwszeństwo przed forAnyRef
i otrzymałem oczekiwane zachowanie?
Dzięki za odpowiedź, Jean. Poprawiając twoje rozwiązanie, wymyśliłem inne rozwiązanie, które pozwala uniknąć tego małego powielania kodu. Zamieszczam to poniżej dla dobra czytelników. – missingfaktor