Прежде всего, немного исторический взгляд на тему от одного из создателей Java. Далее, в Википедии есть довольно полезный раздел о протоколах Objective-C . В частности, следует понимать, что Objective-C поддерживает как формальные протоколы (которые явно объявлены с ключевым словом @protocol
, эквивалентным интерфейсу Java), так и неформальные протоколы (только один или больше методов, реализованных классом, которые можно обнаружить с помощью отражения).
Если вы примете формальный протокол (терминология Objective C для «реализации интерфейса»), компилятор выдаст предупреждения для нереализованных методов, как вы ожидаете в Java. В отличие от Java (как упоминалось skaffman ), если класс Objective-C реализует методы, содержащиеся в формальном протоколе, говорят, что он «соответствует» этому протоколу, даже если его интерфейс не явно принять его. Вы можете проверить соответствие протокола в коде (используя -conformsToProtocol: ) следующим образом:
if ([myObject conformsToProtocol:@protocol(MyProtocol)]) {
...
}
ПРИМЕЧАНИЕ: документация Apple гласит:
"Этот метод определяет соответствие исключительно на основе формальных объявлений в заголовочных файлах, как показано выше. Он не проверяет, действительно ли реализованы методы, объявленные в протоколе, - это ответственность программиста."
Начиная с Objective-C 2.0 (в OS X 10.5 «Леопард» и iOS), формальные протоколы теперь могут определять необязательные методы , и класс соответствует протоколу, если он реализует все необходимые методы. Вы можете использовать ключевые слова @required
(по умолчанию) и @optional
, чтобы переключать, должны ли объявления методов, следующие за , или , могут быть реализованы для соответствия протоколу. (См. Раздел руководства Apple Objective-C 2.0 Language , в котором обсуждаются дополнительные методы протокола .)
Дополнительные методы протокола открывают большую гибкость для разработчиков, особенно для реализации делегатов и слушателей . Вместо того, чтобы расширять что-то вроде MouseInputAdapter (что может раздражать, поскольку Java также является одиночным наследованием) или реализовывать множество бессмысленных, пустых методов, вы можете принять протокол и реализовать только дополнительные методы, которые вам нужны. около. С этим шаблоном вызывающая сторона проверяет, реализован ли метод, прежде чем вызывать его (используя -respondsToSelector ) следующим образом:
if ([myObject respondsToSelector:@selector(fillArray:withObject:)]) {
[myObject fillArray:anArray withObject:foo];
...
}
Если накладные расходы на отражение становятся проблемой, вы всегда можете кэшировать логический результат для повторного использования , но не поддавайтесь желанию оптимизировать преждевременно. : -)