Цель C двухфазное строительство объектов - PullRequest
13 голосов
/ 04 июня 2009

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

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

Ответы [ 2 ]

28 голосов
/ 04 июня 2009

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

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

3 голосов
/ 04 июня 2009

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

...