Ответ 1
Решение Paolo хорошее (+1), но он не объяснил сообщение об ошибке, поэтому позвольте мне попробовать. Проблема связана с тем, что каждому методу нужен тип возврата. Исходное определение apply
и dual
возвратило объект class A
, поэтому неявный возвращаемый тип был A
. Это означает, что A
должен быть видимым для клиентов - как иначе они могли бы вызвать функцию или получить доступ к val
? Более того, поскольку оба - и их родительский объект тоже - являются общедоступными, они глобально видны. Однако вы объявили A private
, что означает, что он не должен быть виден вне его пакета. Таким образом, существует конфликт, который не может быть разрешен компилятором.
Общее правило заключается в том, что все параметры и возвращаемые типы функций/членов должны иметь (по крайней мере) ту же область видимости, что и сам ссылочный элемент *. Таким образом, одним из тривиальных способов решения этой проблемы было бы уменьшить видимость apply
и dual
до private
. Это удовлетворило бы компилятор, но не вы: -)
Ваше решение устраняет проблему, изменяя статический тип возвращаемого значения на public
признак, который, таким образом, имеет ту же видимость, что и члены, ссылающиеся на него. Динамический тип возвращаемого объекта все еще class A
, однако это не должно быть видимым для клиентов. Это классический пример принципа "для интерфейсов, а не для реализации" .
Обратите внимание, что для полного применения этого принципа можно превратить class A
в внутренний класс private
object A
, что делает его недоступным даже для других классов внутри одного пакета:
trait A {
//...
}
object A {
def apply: A = dual
lazy val dual: A = new AImpl
private class AImpl extends A {
//some irrelevant logic...
}
}
* Чтобы быть педантичным, охватывающий класс/объект может уменьшить видимость его элементов, например здесь:
private class Holder {
def member = new Hidden
}
private class Hidden
, где member
есть public
, но его охватывающий класс private
, эффективно скрывая его члены от внешнего мира. Поэтому компилятор не подает никаких жалоб здесь.