2013-03-06 5 views
2

Basic Cocoa newbie question here ... Это похоже на очень распространенный образец в Cocoa. Почему методы init и методы создания автореализованных объектов, такие как [NSArray arrayWithObjects: ...], возвращают id? Почему возвращается NSArray * (или создаваемый тип) не во всех отношениях лучше?Почему NSArray arrayWithObjects и друзья возвращают id, а не NSArray *?

ответ

1

Другая причина заключается в наборе селекторного соответствия возвращаемого значения. Если [NSArray arrayWithObjects: ...] вернул NSArray (по заявлению), то NSMutableArray нужно будет повторно объявить arrayWithObjects: с другим типом возврата (иначе вы получите предупреждение при записи NSMutableArray * a = [NSMutableArray arrayWithArray:]).

Даже если вы пошли по этому маршруту, цепочка сообщений может быстро привести к неоднозначности, когда компилятор пытается сопоставить селекторы с типами/не-типами. Таким образом, в этом сценарии должны совпадать данные о возврате и параметрах выбора. Следовательно, используется тип возврата id.

Если вы попытались построить строго типизированную иерархию objc с такими конструкторами и использовать высокий уровень предупреждения, вы увидите, как разворачивается эта двусмысленность. Конечно, пример NSArray/NSMutableArray достаточен для описания проблемы.

+0

Java и C++ позволяют переопределенным методам иметь ковариантные типы возврата. Тогда у цели нет такой вещи? –

+0

@ Jean-PhilippePellet не рекомендуется использовать этот письменный стиль, особенно если вы имеете дело с объектами без объекта objc. весь необходимый вам динамизм существует, но у компилятора есть сложные типы совпадений типов/селекторов/возвращаемых типов. селектор objc не определяет типы возвращаемых данных или типы параметров (хотя они могут быть запрошены о конкретных реализациях), и отправка всегда динамическая. потому что диспетчирование является динамическим, вы также должны использовать параметр выбора и возвращаемые типы для соответствия. он действительно работает на практике. '[NSMutableArray array]' явно возвращает 'NSMutableArray'. – justin

+0

@ Jean-PhilippePellet (продолжение) несмотря на (исходный уровень) стирание стилей, хотя 'id'. и trojanfoe связало очень хорошее объяснение от bbum. конечно, вы можете попробовать, но инициализаторы и конструкторы, как правило, однострочные, поэтому вы сразу же вводите этот тип, используя объявление переменной. – justin

1

init методы возвращают id, чтобы они могли возвращать тот же класс, что и его суперкласс.

Классы Objective-C возвращают id, поскольку они могут хранить объекты Objective-C любого типа.

+0

См. Мои комментарии к ответам Джастина относительно ковариантных типов возврата –

+0

@ Jean-PhilippePellet No Objective-C не поддерживает ковариантные типы возврата. См. Этот вопрос SO: http://stackoverflow.com/questions/2433504/why-does-gcc-warn-about-incompatible-struct-assignment-with-a-self-super-ini – trojanfoe

+0

ОК, поэтому мой последующий вопрос : почему он не должен возвращать 'instancetype' вместо' id'? –

0

Искренне оно возвращает NSArray/NSMutalbeArray/что угодно.

Именно это id является общим возвращаемым значением init. Таким образом, возвращаемое значение объявляется как id, но это NSArray, который возвращается.

Но, честно говоря, я не могу дать вам никакого хорошего ответа на ваш вопрос «почему». Когда когда-либо я перезаписываю методы init в подклассе, я позволяю им возвращать ABC *, если имя класса - ABC. И это просто отлично работает.

+0

Кажется, что нет проблем с 'init' и некоторые другие специальные методы, потому что [clang рассматривает их специально и автоматически вставляет тип возвращаемого типа instancetype] (http://clang.llvm.org/docs/LanguageExtensions.html#objc_instancetype). –

+0

Это означает, что явным образом заявляю, что класс, который я реализую, не вызывает проблемы напрямую, но может вызвать трудности, если класс, который я сейчас разрабатываю, подклассифицируется позже. –

Смежные вопросы