Вопрос по generics – Как определить классы дел с членами с параметрами несвязанного типа?

6

Дано определение класса с параметром связанного типаAnimal[A <: String] похоже, что компилятор Scala не выводитB <: String отAnimal[B], Разрешен ли вывод? Как помочь компилятору сделать вывод?

Ниже приведен конкретный пример с классами падежей, где отсутствие этого вывода является проблемой.

Рассмотрим следующую иерархию классов дел:

<code>sealed trait Person[+T <: Person[T]]
case class Student() extends Person[Student]
case class Professor() extends Person[Professor]
</code>

Мне нужно определить класс делаUniversity который я могу создать с помощью переменной типаPerson[_], напримерval p: Person[_] = Student(), Я думал, что это будет работать со следующим определением:

<code>case class University(p: Person[_])
</code>

Но это не скомпилируется с ошибкой:

<code>type arguments [Any] do not conform to trait Person's type parameter bounds [+T <: Person[T]]
</code>

Если я связываю параметр типа класса caseUniversity он компилируется (он также компилируется с неограниченными параметрами, если я опускаюcase ключевое слово, но это не вариант в моем случае):

<code>case class BoundUniversity[P <: Person[P]](p: Person[P])
</code>

Но эту параметризованную версию нельзя создать с помощью неограниченной переменной типаPerson[_]:

<code>val p: Person[_] = Student()
BoundUniversity(p)
</code>

не компилируется с:

<code>inferred type arguments [_$1] do not conform to method apply's type parameter bounds [P <: Person[P]]
</code>

Та же ошибка происходит для метода со связанным аргументом, например:

<code>def general[P <: Person[P]](p: P) = println(p)
</code>

так что это не относится к конструкторам классов.

Два вопроса:

The type Person is defined with parameter bounds Person[+T <: Person[T]], so that each instance of this type is insured to respect those bounds: val p: Person[P] implies that P <: Person[P]; or am I missing something? So how can I make this clear to the compiler so that it doesn't complain?

How/Can I define a case class with members with unbound type parameter like case class University(p: Person[_])?

ДелаетT должен быть ковариантным? leedm777
@ Дэйв в моем конкретном случаеT должен быть ковариантным, но я думаю, что это не меняет проблему: см. вводный пример. Julien Gaugaz
Ты можешь куда-нибудь добраться, используя абстрактные типы но потом они становятся довольно инвариантный. leedm777

Ваш Ответ

1   ответ
2

X[_] вряд ли когда-нибудь, что вы хотите. Когда вы используете_ для типа вы в основном говорите, что вам все равно, что это за параметр, потому что вам никогда не понадобится его использовать.

Во всяком случае, это компилируется. Это может укусить вас в будущем, потому что экзистенциальные типы - хитрая штука, но ...

case class University(p: Person[t] forSome { type t <: Person[t] })
Я полагаю, что вы проверили свой код перед публикацией. Я только что протестировал его с нуля, мне не удалось его скомпилировать на моей машине с помощью scalac 2.9.1.final (с вашимUniversity и мойPerson определения). Я постараюсь копаться в этом дальше. В любом случае, спасибо за подсказку о экзистенциальных типах! Julien Gaugaz
Отличный экзистенциальный тип, спасибо! Это компилируется, но не может быть создан с помощьюval p: Person[_] = Student(); University(p). ТипPerson[_] Я упомянул, приходит из списка:List[Person[_]](Student(), Professor()). Обратите внимание, чтоList(Student(), Professor()) не компилируется. Я чувствую, что здесь есть какая-то картина, но я не могу на это указать ... Julien Gaugaz
На самом деле это не показывает ошибки в моем Eclipse, но не компилируется сscalac. Типа misttach, найденоPerson[(some other)_1(in method equals)] where type (some other)_1(in method equals) <: schemdesc.hierarchy.eval.Person[_0], обязательныйPerson[_ <: schemdesc.hierarchy.eval.Person[_0]] Julien Gaugaz
@ jullybobble Приведенная выше строка компилируется - я проверял это. Если у вас есть проблема с компиляцией, вы делаете что-то другое. И вы не можете использоватьPerson[_] - это не сработает. Вы должны использовать экзистенциальный тип выше, если хотите, чтобы он работал. Daniel C. Sobral

Похожие вопросы