Ответ 1
Для простого случая, когда A
и B
связаны компилятором в то же время, что и T
, ответ IttayD отлично работает:
def f[T, A <: T,B <: T](a:A, b:B) = List[T](a,b)
Когда A
и B
уже связаны как в вашем примере class Foo[A, B]
, вам нужно ввести временные фиктивные переменные, чтобы компилятор выполнил это задание:
class Foo[A, B](a: A, b: B) {
def g[T, A1 >: A <: T, B1 >: B <: T] = List[T](a.asInstanceOf[T], b.asInstanceOf[T])
}
(Для ясности: A1 >: A <: T
означает, что тип A1
должен быть супертипом A
и подтипом T
, а не тем, что A
является подтипом как A1
, так и T
.)
A1
и B1
приведены здесь с единственной целью вывести правильный тип для T
. Если компилятор должен их вывести, они будут разрешены к A1 = A
и B1 = B
, а затем T
как наиболее конкретный тип, который является суперклассом как A
, так и B
.
Однако одна вещь, которую компилятор не понимает, заключается в том, что по транзитивности мы имеем как T >: A
, так и T >: B
, которые непосредственно следуют из ограничений по A1
и B1
. Поэтому мы должны явно бросить здесь. Но здесь литье всегда безопасно.
Теперь Product#productIterator
не мог использовать эту технику, как она определена в месте, где мы даже не знаем A
и B
, или действительно, сколько параметров типа есть в конкретном подклассе.