Ответ 1
В Scala внутренние классы являются "зависимыми от пути".
Я буду использовать ваш код в качестве примера. Если у вас есть два Foo[Int]
s, называемые foo
и bar
, то foo.Bar
- это другой тип bar.Bar
. Обратите внимание, что это отличается от идеи Java внутренних классов, где foo.Bar
и bar.Bar
являются одним и тем же типом.
В любом случае JVM не поддерживает внутренние классы напрямую, поэтому в Java и Scala класс Bar компилируется в класс JVM под названием Foo$Bar
. Экземпляры внутренних классов почти всегда содержат ссылку на своего владельца - "внешнюю ссылку".
Теперь, когда у вас есть соответствие шаблона по типу, зависящему от пути (например, в коде), компилятор Scala будет генерировать байт-код, который выполняет две функции: он проверит класс (поэтому он будет проверять что объект, который он получил, является экземпляром Foo$Bar
), и он проверит внешнюю ссылку (поэтому он проверит, что внешняя ссылка полученного объекта foo
).
Однако в вашем коде компилятор не может найти способ проверить внешнюю ссылку, потому что вы объявили свой внутренний класс окончательным.
Итак, если вы проигнорируете предупреждение, ваш шаблон будет соответствовать всем экземплярам Foo$Bar
, даже если они не принадлежат foo
. У вас будет лучшая идея, чем у меня, будет ли это проблемой.
Или вы можете исправить это, сделав свой внутренний нечетный класс.
Ps, я не совсем уверен, почему компилятор Scala не может проверить внешние ссылки на конечных внутренних классах, но я обнаружил, что если внутренний класс является окончательным, то outer$
является закрытым, тогда как if он не является окончательным, outer$
является общедоступным. Возможно, стоит подумать о том, что это такое.
Update
Оказывается, это известная проблема - SI-4440. Компилятор Scala отбрасывает внешние ссылки для конечных внутренних классов, если они не используются (что является неопределенно законным, так как нет возможности использования их подклассов). Одним из положительных последствий этого является то, что внешние классы могут быть собраны в мусор, пока внутренние классы все еще используются, поэтому разработчики Scala неохотно повторно вводят внешние ссылки, опасаясь ввести утечки памяти.