Протокол против категории

Может кто-нибудь объяснить различия между протоколами и категориями в Objective-C? Когда вы используете один над другим?

11.12.2008 21:22:23
7 ОТВЕТОВ
РЕШЕНИЕ

Протокол - это то же самое, что интерфейс в Java: по сути, это контракт, который говорит: «Любой класс, реализующий этот протокол, также будет реализовывать эти методы».

Категория, с другой стороны, просто привязывает методы к классу. Например, в Какао я могу создать категорию NSObject, которая позволит мне добавлять методы в NSObjectкласс (и, конечно же, все подклассы), даже если у меня нет к нему доступаNSObject .

Подводя итог: протокол указывает, какие методы реализует класс; категория добавляет методы к существующему классу.

Таким образом, правильное использование каждого из них должно быть ясным: используйте протоколы для объявления набора методов, которые должен реализовать класс, и используйте категории для добавления методов в существующий класс.

90
14.06.2012 14:00:33

Категории:

Категория - это способ добавления новых методов ко всем экземплярам существующего класса без изменения самого класса.

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

Допустим, вы используете NSViewобъекты в какао, и вам хочется, чтобы все экземпляры NSViewмогли выполнить какое-то действие. Очевидно, что вы не можете переписать NSViewкласс, и даже если вы его NSViewнаследуете , не все объекты в вашей программе будут вашего производного типа. Решение состоит в том, чтобы создать категорию NSView, которую вы затем используете в своей программе. Пока вы #importиспользуете заголовочный файл, содержащий объявление вашей категории, он будет выглядеть так, как будто каждый NSView объект реагирует на методы, которые вы определили в исходном файле категории.

Протоколы:

Протокол - это набор методов, которые любой класс может выбрать для реализации.

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

Это может быть полезно при создании семейства похожих классов, которые должны взаимодействовать с общим классом «контроллера». Связь между классом контроллера и управляемыми классами может быть упакована в один протокол.

Примечание: язык Objective-C не поддерживает множественное наследование (класс может быть производным только от одного суперкласса), но большая часть той же функциональности может быть обеспечена протоколами, потому что класс может соответствовать нескольким различным протоколам.

16
12.12.2008 00:51:22

Насколько я понимаю, протоколы немного похожи на интерфейсы Java. Протоколы объявляют методы, но реализация зависит от каждого класса. Категории кажутся чем-то вроде миксинов Руби. С помощью категорий вы можете добавлять методы в существующие классы. Даже встроенные классы.

5
11.12.2008 21:44:35

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

Теперь я подозреваю, что ваше замешательство связано с использованием Apple фразы «неофициальный протокол». Вот ключевой (и самый запутанный) момент: неформальный протокол на самом деле не является протоколом вообще. На самом деле это категория по NSObject. Какао широко использует неформальные протоколы для предоставления интерфейсов для делегатов. Поскольку @protocolсинтаксис не позволял использовать дополнительные методы до Objective-C 2.0, Apple реализовала дополнительные методы, чтобы ничего не делать (или возвращать фиктивное значение), и требовала, чтобы методы вызывали исключение. Не было никакого способа обеспечить это через компилятор.

Теперь в Objective-C 2.0 @protocolсинтаксис поддерживает @optionalключевое слово, помечая некоторые методы в протоколе как необязательные. Таким образом, ваш класс соответствует протоколу, если он реализует все методы, помеченные как @required. Компилятор может определить, реализует ли ваш класс все необходимые методы, что значительно экономит время. IPhone SDK использует исключительно @protocolсинтаксис Objective-C 2.0 , и я не могу найти вескую причину не использовать его в каких-либо новых разработках (за исключением приложений Mac OS X Cocoa, которые должны работать в более ранних версиях Mac OS X) ,

29
11.12.2008 21:56:44

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

Категории предоставляют возможность расширять текущий объект, добавляя к нему методы (методы класса или экземпляра). Хорошим использованием для категории было бы расширение класса NSString для добавления функциональности, которой раньше не было, например, добавление метода для создания новой строки, которая преобразует получатель в 1337 5P34K.

NSString *test = @"Leet speak";
NSString *leet = [test stringByConvertingToLeet];
1
19.03.2009 10:11:56

Протокол позволяет вам объявить список методов, которые не ограничены каким-либо конкретным классом или категориями. Методы, объявленные в протоколе, могут быть приняты любым классом / категориями. Класс или категория, которые принимают протокол, должны реализовывать все необходимые методы, объявленные в протоколе.

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

3
4.09.2011 18:53:37

Определения С.Г.Кочана "Программирование в Objective-C":

Категории:

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

Протоколы:

Протокол - это список методов, которые совместно используются классами. Методы, перечисленные в протоколе, не имеют соответствующих реализаций; они предназначены для реализации кем-то другим (как вы!). Протокол предоставляет способ определения набора методов, которые так или иначе связаны с указанным именем. Методы обычно документируются, чтобы вы знали, как они должны работать, и чтобы вы могли реализовать их в своих определениях классов, если это необходимо. Протокол содержит список методов, некоторые из которых вы можете реализовать по желанию, а другие - для реализации. Если вы решите внедрить все необходимые методы для определенного протокола, вы должны будете принять или принять этот протокол. Вам разрешено определять протокол, в котором все методы являются необязательными, или протокол, в котором все требуются.

1
14.06.2012 11:00:00