Действительно, все ваши вопросы проистекают из одного и того же недопонимания.
Вы определили как "класс с параметром типа и метод foo, который может работать с любым типом descended из T , из которого происходит T.
Вы предоставили класс с foo, который может действовать на T, но не обязательно для потомков (на самом деле, поскольку аргументыковариантно, foo на самом деле будет работать с потомками, но спецификация недостаточно точна, чтобы это уловить) суперклассы T.
В двух других вопросах вы случайно повторно использовали имя существующего типа.Когда вы писали foo [Date] или foo [String], вы ссылались не на java.lang.String или java.lang.Date, как вы, очевидно, думали, а на новые типы с тем же именем! Вот почему вы видите несоответствиеString и java.lang.String - это два разных типа.
Попробуйте вместо этого:
abstract class A[+T] { def foo[S >: T](x: S): String }
class B extends A[String] { def foo[S >: String](x: S) = x.toString }
Да, S >: String
бессмысленно, так какСтрока является окончательной, но спецификация не можетЯ вырезал все возможные варианты.
ПРИМЕЧАНИЕ Я тоже что-то вроде тирона, поэтому не удивляйтесь, если мой ответ неверен / вводит в заблуждение.И помните: этот совет гарантированно стоит вдвое больше, чем вы заплатили за него или ваши деньги были возвращены.
TOLD YA Большая ошибка: я поменял суперкласс и подкласс.Исправления, сделанные в соответствии с вычеркиванием .
ПРИМЕР ОП не ясно, зачем все это необходимо.Рассмотрим следующую функцию
def foo3(a : A[String]) = a.foo(3)
Это допустимо, потому что 3 (как java.lang.Integer) является примером объекта, который является предком A. Если B.foo были определены как получение String иничего другого, экземпляр B не может быть передан в foo3.