Подтвердить что ты не робот

Является ли подкласс в Objective-C плохой практикой?

После прочтения большого количества блогов, записей в форуме и нескольких документов Apple, , я до сих пор не знаю, является ли обширное подклассов в Objective-C разумным делом или нет.

Возьмем, к примеру, следующий случай:

Скажем, я разрабатываю игру-головоломку, в которой имеет много элементов. Все из тех элементы разделяют определенное количество такое же поведение. Затем, в пределах моего сбор элементов, разные группы элементов разделяют равные поведение, отличаясь от групп и т.д.

Итак, после определения того, что наследует от чего, я решил подкласс забвения. И почему я не должен?Учитывая легкость настройки поведение с этой моделью, я думаю, что я достиг чего-то ООП предназначенный для.

Но, - и это является источником моего вопроса - Apple упоминает , используя делегатов, методы источника данных и неофициальные протоколы в пользу подкласса. Это действительно пугает мой разум, почему?

Кажется, что есть два лагеря. Те, кто выступает за подклассификацию, в фафоре нет. По-видимому, это зависит от личного вкуса. Мне интересно, какие плюсы и минусы являются подклассом массово и не подклассифицируются массово?

Чтобы обернуть это, мой вопрос прост: Я прав? А почему или почему нет?

4b9b3361

Ответ 2

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

Использование комбинации делегатов и протоколов (для определения того, что должны делать делегаты) обеспечивает большую гибкость поведения и простоту кодирования - возвращаясь к этому принципу подстановки Лискова, когда вы подклас чтобы быть осторожным, вы ничего не делаете, что пользователь всего класса окажется неожиданным. Но если вы просто создаете объект-делегат, вам гораздо меньше нести ответственность, только то, что применяемые вами методы-делегаты делают то, что требует этот протокол, кроме того, вам все равно.

Есть еще много веских оснований для использования подклассов, если у вас действительно есть совместное поведение и переменные между несколькими классами, это может иметь большой смысл для подкласса. Но если вы можете воспользоваться концепцией делегата, вы часто будете расширять или использовать ваши классы так, как вы, возможно, не ожидали дизайнер.

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

Ответ 3

Подклассификация имеет преимущества, но также имеет некоторые недостатки. Как правило, я стараюсь избегать наследования реализации и вместо этого использовать наследование интерфейса и делегирование.

Одна из причин, по которой я это делаю, заключается в том, что, когда вы наследуете реализацию, вы можете столкнуться с проблемами, если вы переопределяете методы, но не придерживаетесь их (иногда недокументированного контракта). Кроме того, я нахожу иерархии ходячих классов с наследованием реализации сложными, потому что методы могут быть переопределены или реализованы на любом уровне. Наконец, при подклассе вы можете только расширить интерфейс, вы не можете его сузить. Это приводит к негерметичным абстракциям. Хорошим примером этого является java.util.Stack, который расширяет java.util.Vector. Я не должен обрабатывать стек как вектор. Это позволяет только потребителю бегать по интерфейсу.

Другие упомянули Принцип замещения Лискова. Я думаю, что использование этого вопроса, несомненно, прояснило бы проблему java.util.Stack, но также может привести к очень глубоким иерархиям классов, чтобы гарантировать, что классы получают только те методы, которые они должны иметь.

Вместо этого, с наследованием интерфейсов по существу нет иерархии классов, поскольку интерфейсы редко нуждаются в расширении друг друга. Классы просто реализуют интерфейсы, в которых они нуждаются, и поэтому могут быть правильно обработаны потребителем. Кроме того, поскольку наследования реализации нет, потребители этих классов не будут выносить свое поведение из-за предыдущего опыта с родительским классом.

В конце концов, не имеет значения, в каком направлении вы идете. Оба они вполне приемлемы. Это больше зависит от того, с чем вам более комфортно, и с какими структурами, с которыми вы работаете, поощряете. Как говорится в старой поговорке: "Когда в Риме делают то, что делают римляне".

Ответ 4

Нет ничего плохого в использовании наследования в Objective-C. Apple использует его совсем немного. Например, в Cocoa -touch дерево наследования UIButton - UIControl: UIView: UIResponder: NSObject.

Я думаю, что Мартин затронул важный момент, упоминая принцип замещения Лискова. Кроме того, правильное использование наследования требует, чтобы исполнитель подкласса имел глубокое знание суперкласса. Если вы когда-либо пытались расширить нетривиальный класс в сложной структуре, вы знаете, что всегда есть кривая обучения. Кроме того, детали реализации суперкласса часто "просачиваются" в подкласс, что является большой болью в @$& для разработчиков каркаса.

Apple решила использовать делегирование во многих случаях для решения этих проблем; нетривиальные классы, такие как UIApplication, выставляют общие точки расширения через объект-делегат, поэтому большинство разработчиков имеют как более легкую кривую обучения, так и более свободно связанный способ добавления специфического для приложения поведения. Прямое распространение UIApplication редко бывает необходимо.

В вашем случае для вашего конкретного кода приложения используйте те методы, которые вам удобны и которые лучше всего подходят для вашего дизайна. Наследование является отличным инструментом при правильном использовании.

Я часто вижу, как программисты приложений извлекают уроки из рамочных проектов и пытаются применить их к их прикладному коду (это распространено в мирах Java, С++ и Python, а также Objective-C). Хотя хорошо подумать и понять, какие дизайнерские решения выбора сделали, эти уроки не всегда применяются к коду приложения.

Ответ 5

В целом вам следует избегать классов подкласса API, если есть делегаты и т.д., которые выполняют то, что вы хотите сделать. В вашем собственном подклассе кода часто лучше, но это действительно зависит от ваших целей, например. если вы предоставляете API, вы должны предоставить API на основе делегатов, а не предполагать подклассы.

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

Ответ 6

Прочитайте документацию Apple Добавление поведения в программу Cocoa. В разделе " Наследование класса Cocoa см. Во втором абзаце. Apple ясно упоминает, что Subclassing является основным способом добавления специфического для приложения поведения в структуру (обратите внимание, FRAMEWORK).
Шаблон MVC не полностью запрещает использование подклассов или подтипов. По крайней мере, я не видел эту рекомендацию ни от Apple, ни от других (если я пропустил, не стесняйтесь указывать мне правильный источник информации об этом). Если вы подклассифицируете классы api только в своем приложении, пожалуйста, продолжайте, никто вас не останавливает, но позаботьтесь о том, чтобы он не нарушал поведение класса /api в целом. Подкласс - отличный способ расширить функциональность фреймворка api. Мы также видим много подклассов в API-интерфейсах API Apple IOS. Как разработчик нужно заботиться о том, чтобы реализация была хорошо документирована и не дублировалась другим разработчиком. Его еще одна игра с мячом, если ваше приложение представляет собой набор классов API, которые вы планируете распространять как компонент многократного использования.

ИМХО, а не спрашивать, что такое лучшая практика, сначала внимательно прочитайте соответствующую документацию, внесите в нее и протестируйте ее. Сделайте свое собственное суждение. Вы лучше знаете, что вы делаете. Легко для других (таких как я и многие другие) просто читать материал из разных источников в Сети и бросать слова. Будь вашим собственным судьей, он работал у меня до сих пор.

Ответ 7

Я действительно думаю, что это зависит от того, что вы пытаетесь сделать. Если игра-головоломка, которую вы описываете в примере, действительно содержит набор уникальных элементов, которые имеют общие атрибуты, и нет предоставленных классов - например, "NSPuzzlePiece" - которые соответствуют вашим потребностям, то я не вижу проблемы с большим подклассом.

По моему опыту, делегаты, методы источника данных и неофициальные протоколы гораздо полезнее, когда Apple предоставила класс, который уже делает что-то близкое к тому, что вы хотите.

Например, скажем, что вы создаете приложение, которое использует таблицу. Существует (и я говорю здесь об iPhone SDK, так как у меня есть опыт) класс UITableView, который делает все небольшие тонкости создания таблицы для взаимодействия с пользователем, и гораздо эффективнее определить источник данных для экземпляр UITableView, чем для полного подкласса UITableView и переопределения или расширения его методов для настройки его поведения.

Аналогичные концепции идут для делегатов и протоколов. Если вы можете поместить свои идеи в классы Apple, тогда обычно проще (и будет работать более плавно), чтобы сделать это, и использовать источник данных, делегаты и протоколы, чем создавать свои собственные подклассы. Это помогает избежать дополнительной работы и тратить время и, как правило, менее подвержено ошибкам. Классы Apple позаботились о том, чтобы сделать функции эффективными и отладки; чем больше вы сможете работать с ними, тем меньше ошибок будет иметь ваша программа в конечном итоге.

Ответ 8

Мое впечатление от акцента ADC "против" подкласса больше связано с наследием развития операционной системы... в тот же день (Mac Classic aka os9), когда С++ был основным интерфейсом для большинства Mac инструментарий, подклассификация была стандартом де-факто, чтобы программист мог изменить поведение обычных функций ОС (и это действительно было иногда болью в шее и означало, что нужно быть очень осторожным, чтобы любые изменения и все изменения вели себя предсказуемо и не нарушали стандартного поведения).

Это говорит о том, что МОЙ ВПЕЧАТЛЕНИЕ акцент ADC на подклассификацию не ставит случая для разработки иерархии классов приложений без наследования, НО INSTEAD указывает, что в новом способе делать вещи ( т.е. OSX), в большинстве случаев есть более подходящие средства для настройки стандартного поведения без необходимости подкласса.

Итак, во что бы то ни стало, создайте архитектуру вашей головоломки так же хорошо, как можете, используя наследование, как вы сочтете нужным!

с нетерпением жду вашего замечательного нового приложения для головоломок!

| К <

Ответ 9

Apple действительно, похоже, пассивно препятствует подклассу Objective-C.

Это аксиома дизайна ООП для поддержки композиции над реализацией.