(Примечание: мотивация для этого требует долгого и трудного объяснения, вы можете найти полное обсуждение этой
Как я могу доказать, что два типа не имеют отношения подтипирования в Scala?
Ответ 1
Если вы хотите принудительно установить, что два типа сильно отличаются во время компиляции, тогда это вопрос для вас. Используя один из ответов, который определяет =!=
, мы можем представить несколько методов, которые выглядят следующим образом:
implicit class Extend[T](lhs: T) {
def testAgainst(rhs: T) = println("same type")
def testAgainst[U](rhs: U)(implicit ev: T =!= U) = println("different type")
}
Мы также можем легко выполнить тест типа в рамках одного метода, используя TypeTag
.
import scala.reflect.runtime.universe._
implicit class Extend[T: TypeTag](lhs: T) {
def testAgainst[U: TypeTag](rhs: U): Boolean = typeOf[T] =:= typeOf[U]
}
Вы могли бы, конечно, изменить его, чтобы развернуть поведение.
scala> 1 testAgainst 2
res98: Boolean = true
scala> 1 testAgainst "a"
res99: Boolean = false
scala> List(1, 2, 3) testAgainst List(true, false)
res100: Boolean = false
scala> List(1, 2) testAgainst List.empty[Int]
res102: Boolean = true
Ответ 2
Решение на самом деле довольно простое. Ваша единственная реальная проблема заключается в том, что обе ваши перегрузки имеют одно и то же стирание, что является лишь проблемой для компилятора из-за ограничений базовой JVM. Что касается ввода текста, то наличие этих двух перегрузок отлично.
Итак, все, что вам нужно сделать, это изменить подпись одной перегрузки таким образом, чтобы она была функционально эквивалентна. Это можно сделать с использованием неявного параметра, который всегда будет найден (обычно, стандартной библиотеки DummyImplicit
) или путем добавления фиктивного параметра со значением по умолчанию. Так что любой из них в порядке (я обычно использую первую версию):
def testAgainst[U](rhs: U)(implicit dummy: DummyImplicit) = println("different type")
или
def testAgainst[U](rhs: U, dummy: Int = 0) = println("different type")
Ответ 3
Существует также способ определить во время выполнения, что не существует отношения подтипирования между типами, основанными на неявных правилах разрешения и неявных значениях по умолчанию. Это можно проиллюстрировать этой простой функцией и ее вызовами:
scala> def checkSubtypes[T, U](implicit ev: T <:< U = null) = ev
checkSubtypes: [T, U](implicit ev: <:<[T,U])<:<[T,U]
scala> checkSubtypes[Int, Long]
res4: <:<[Int,Long] = null
scala> checkSubtypes[Integer, Number]
res5: <:<[Integer,Number] = <function1>
Если тип T
не является подтипом другого типа U
, компилятор не сможет найти неявное значение для T <:< U
, и поэтому будет использоваться значение по умолчанию, которое равно null
в этом случае.
Это, однако, будет работать только во время выполнения, поэтому, вероятно, это точно не отвечает на ваш вопрос, но, тем не менее, этот трюк может быть полезен иногда.