Если вы на самом деле переопределяете метод generi c, вы должны реализовать его для всех возможных типов параметров типа (в противном случае вы нарушаете контракт класса):
trait BearLike {
def drink[T](str: String)
}
case class Bear(a: String, b: String) extends BearLike {
override def drink[T](str: String) = ??? // for all T
}
или
case class Bear(a: String, b: String) {
def drinkABCD[T](str: String)(implicit can: Can[T]) = can.open(str) // only for A, ..., D
}
или
case class Bear(a: String, b: String) extends BearLike {
override def drink[T](str: String): Unit = sys.error("Bear is not actually a BearLike")
def drinkABCD[T](str: String)(implicit can: Can[T]) = can.open(str) // only for A, ..., D
}
при условии, что есть Can[A]
, ..., Can[D]
trait Can[T] {
def open(str: String)
}
object Can {
implicit val a: Can[A] = ???
implicit val b: Can[B] = ???
implicit val c: Can[C] = ???
implicit val d: Can[D] = ???
}
Если вы можете изменить договор, то Вы можете добавить это ограничение (чтобы метод работал только для A
, ..., D
) к контракту
trait BearLike {
def drink[T](str: String)(implicit can: Can[T])
}
case class Bear(a: String, b: String) extends BearLike {
override def drink[T](str: String)(implicit can: Can[T]) = can.open(str)
}
Иногда комбинировать FP (классы типов) с * 1026 нелегко * (наследство). Обычно, если вы начинаете работать с классами типов (Can
), вам следует предпочесть классы типов дальше
trait BearLike[B] {
def drink(str: String)
}
case class Bear[T](a: String, b: String)
object Bear {
implicit def bearIsBearLike[T](implicit can: Can[T]): BearLike[Bear[T]] = new BearLike[Bear[T]] {
override def drink(str: String): Unit = can.open(str)
}
}