Протокол против категории - PullRequest
36 голосов
/ 12 декабря 2008

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

Ответы [ 7 ]

89 голосов
/ 12 декабря 2008

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

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

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

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

29 голосов
/ 12 декабря 2008

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

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

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

16 голосов
/ 12 декабря 2008

Категории:

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

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

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

Протоколы:

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

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

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

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

5 голосов
/ 12 декабря 2008

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

3 голосов
/ 04 сентября 2011

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

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

1 голос
/ 14 июня 2012

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

Категории:

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

Протоколы:

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

1 голос
/ 19 марта 2009

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

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

NSString *test = @"Leet speak";
NSString *leet = [test stringByConvertingToLeet];
...