Работа внутри конструктора
Обычно я делаю дорогие вещи внутри конструктора. Но обратите внимание, что в комментариях упоминается, что код конструктора может быть менее оптимизирован (вставьте сюда реализацию Java, для которой это правильно). Также прочитайте следующий параграф, если у вас есть многопоточное приложение.
Задержка инициализации
Я не знаю ничего, что могло бы быть неправильно при выполнении большого количества работы внутри конструктора.
Как отмечено в комментариях, могут быть проблемы с кодом, выполняющимся внутри конструктора, относительно параллелизма. Для этого черта DelayedInit
была введена в Scala 2.8.0. Проблемы такого рода возникают, например, при работе с элементами графического интерфейса Swing.
Черта DelayedInit
предоставляет еще один инструмент для настройки
последовательности инициализации классов и объектов. Если класс или объект
наследует от этой черты, весь его код инициализации упакован в
замыкание и переадресация в качестве аргумента метода с именем delayedInit
который определяется как абстрактный метод в признаке DelayedInit.
Реализации delayedInit, таким образом, имеют полную свободу при выполнении
код инициализации. Например, новые фирменные магазины Scala App
все последовательности инициализации во внутреннем буфере и выполняет их
когда вызывается основной метод объекта.
Ленивые Конструкции
Чтобы отложить вычисления другим способом, вы можете использовать следующие методы, которые также решают проблему параллелизма:
- Вы можете использовать
lazy val
членов, которые будут вычислены при первом запросе.
- Если вы вычисляете последовательность дорогих объектов, вы можете использовать «ленивую» структуру данных, такую как
Stream
. Это похоже на List
, который вычисляет следующий элемент только по требованию. Таким образом, в определенный момент времени была вычислена только начальная часть Stream
, к которой уже был получен доступ.
Показания к применению lazy
Еще одно соображение, которое вы могли бы сделать, это то, будут ли вычисленные значения использоваться вообще. Если они могут и не понадобиться, используйте описанные мной ленивые методы. С другой стороны, если вы определенно получите доступ к этим дорогостоящим элементам, по моему мнению, нет ничего плохого в выполнении вычислений внутри конструктора, а использование ленивых членов может добавить ненужные вычислительные затраты.
Примечание относительно примера OP
Нельзя делать опасные вещи внутри конструктора; подобно тому, как позволить ссылкам на частично построенный объект ускользать от конструктора (через this
-reference). Пример внутри OP делает это с calc.perform(this)
. Эта «потенциальная ошибка» не может быть исправлена с помощью следующих предложений.