Объективная C двухфазная конструкция объектов

Я читал о RAII и одинарной и двухфазной конструкции/инициализации. По какой-то причине я был в двухэтапном лагере до недавнего времени, потому что в какой-то момент я, должно быть, слышал, что плохо делать операции с ошибками в вашем конструкторе. Однако я думаю, что теперь я убежден, что однофазный предпочтительнее, основываясь на вопросах, которые я прочитал о SO и других статьях.

Мой вопрос: почему Objective C использует двухфазный подход (alloc/init) почти исключительно для конструкторов без удобства? Есть ли какая-то конкретная причина в языке, или это просто дизайнерское решение дизайнеров?

Ответы

Ответ 1

У меня есть завидная ситуация с работой для парня, который написал +alloc еще в 1991 году, и мне довелось задать ему очень похожий вопрос несколько месяцев назад. Добавление +alloc состояло в том, чтобы предоставить +allocWithZone:, который был для добавления пулов памяти в NeXTSTEP 2.0, где память была очень плотной (4M). Это позволило вызывающему абоненту управлять тем, где объекты были выделены в памяти. Это была замена +new и ее родственников, которая была (и продолжает оставаться, хотя ее никто не использует), 1-фазным конструктором, основанным на Smalltalk new. Когда Cocoa перешло в Apple, использование +alloc уже было укоренилось, и в +new не было возврата, хотя фактически выбор вашего NSZone редко имеет существенное значение.

Таким образом, это не большой философский вопрос 1 фазы /2 фазы. На практике Cocoa имеет однофазную конструкцию, потому что вы всегда (и всегда должны) вызывать их поочередно в одном вызове без теста на +alloc. Вы можете думать об этом как о сложном способе ввода "нового".

Ответ 2

Мой опыт связан с С++, но одним недостатком С++ однофазной инициализации является обработка наследования/виртуальных функций. В С++ вы не можете вызывать виртуальные функции во время строительства или уничтожения (ну, вы можете, он просто не будет делать то, что вы ожидаете), Двухэтапный init мог бы решить эту проблему (частично. Из того, что я понимаю, он будет перенаправлен в нужный класс, но init, возможно, еще не закончил. Вы все еще можете с этим поделать) (я все еще поддерживаю одна фаза)