Тип союза с верхней границей
Я следовал методу, представленному в принятом ответе на этот вопрос
Как определить "тип дизъюнкции" (типы объединения)?, чтобы поддерживать проверку типа для многотипного параметра для метода.
Неявные "доказательства"
@implicitNotFound(msg="Only String, Array[Byte] and InputStream are supported")
sealed class Input[T]
object Input{
implicit object ByteArrayWitness extends Input[Array[Byte]]
implicit object StringWitness extends Input[String]
implicit object InputStreamWitness extends Input[InputStream]
}
Метод API
def foo[T: Input](param: T) =
param match {
case x: String => //...
case x: Array[Byte] => //...
case x: InputStream => //...
case _ => throw new UnsupportedOperationException(s"not implemented for type ${param.getClass}")
}
Проблема
этот компилирует
foo("test")
foo(Array[Byte](123.toByte))
но это не так (потому что это не конкретный InputStream
)
foo(new ByteArrayInputStream("abc".getBytes("UTF-8")))
Мне нужно передать его точному супер-типу, чтобы он работал (это компилируется)
foo(new ByteArrayInputStream("abc".getBytes("UTF-8")).asInstanceOf[InputStream])
Есть ли способ изменить
implicit object InputStreamWitness extends Input[InputStream]
Итак, это доказательство всего, что распространяется на InputStream
? У меня есть ощущение, что есть какая-то верхняя граница <:
нотации, чтобы подключиться где-то, я просто не знаю, где...
Или это, когда на помощь приходит "сумасшедший материал исчисления лямбды" от самого высокого проголосовавшего ответа на вышеупомянутый вопрос?
Ответы
Ответ 1
Сделайте Input
contra variant в типе T
как: Input[-T]
, это означает, что если A является супер-типом B, то вход [B] является супер-типом ввода [A] (обратное "наследование" ), В вашем случае это просто означает, что Input [InputStream] знает, как обрабатывать все типы ввода подкласса InputStream
(например, ByteArrayInputStream
)
Мне действительно нравится объяснение контравариантности Рекса Керра в этом вопросе. Но есть много других.