Это не компилируется:
class MyClass[+A] {
def myMethod(a: A): A = a
}
//error: covariant type A occurs in contravariant position in type A of value a
Хорошо, достаточно справедливо.Но это компилируется:
class MyClass[+A]
implicit class MyImplicitClass[A](mc: MyClass[A]) {
def myMethod(a: A): A = a
}
Что позволяет нам обойти любые проблемы, которые дает нам проверка на отклонения:
class MyClass[+A] {
def myMethod[B >: A](b: B): B = b //B >: A => B
}
implicit class MyImplicitClass[A](mc: MyClass[A]) {
def myExtensionMethod(a: A): A = mc.myMethod(a) //A => A!!
}
val foo = new MyClass[String]
//foo: MyClass[String] = MyClass@4c273e6c
foo.myExtensionMethod("Welp.")
//res0: String = Welp.
foo.myExtensionMethod(new Object())
//error: type mismatch
Это похоже на обман.Следует ли этого избегать?Или есть какая-то законная причина, по которой компилятор позволяет ему скользить?
Обновление:
Рассмотрим это, например:
class CovariantSet[+A] {
private def contains_[B >: A](b: B): Boolean = ???
}
object CovariantSet {
implicit class ImpCovSet[A](cs: CovariantSet[A]) {
def contains(a: A): Boolean = cs.contains_(a)
}
}
Это, безусловно, выглядитнам удалось достичь невозможного: ковариантный «набор», который все еще удовлетворяет A => Boolean
.Но если это невозможно, не должен ли это запретить компилятор?