Я знаю Java, а сейчас изучаю Objective-C. В чем именно разница между интерфейсами Java и протоколами Objective-C?
Я знаю Java, а сейчас изучаю Objective-C. В чем именно разница между интерфейсами Java и протоколами Objective-C?
Ответы:
Во-первых, небольшой исторический взгляд на тему от одного из создателей Java. Далее в Википедии есть умеренно полезный раздел о протоколах Objective-C . В частности, следует понимать, что Objective-C поддерживает как формальные протоколы (которые явно объявляются с @protocol
ключевым словом, эквивалент интерфейса Java), так и неформальные протоколы (только один или несколько методов, реализованных классом, которые можно обнаружить с помощью отражения).
Если вы применяете формальный протокол (терминология Objective-C для «реализации интерфейса»), компилятор будет выдавать предупреждения для нереализованных методов, как и следовало ожидать в Java. В отличие от Java (как упоминал скаффман ), если класс Objective-C реализует методы, содержащиеся в формальном протоколе, говорят, что он «соответствует» этому протоколу, даже если его интерфейс явно не принимает его.Вы можете проверить соответствие протокола в коде (используя -conformsToProtocol :) следующим образом:
if ([myObject conformsToProtocol:@protocol(MyProtocol)]) {
...
}
ПРИМЕЧАНИЕ. В документации Apple указано:
«Этот метод определяет соответствие исключительно на основе формальных объявлений в файлах заголовков, как показано выше. Он не проверяет, реализованы ли методы, объявленные в протоколе, на самом деле - это ответственность программиста».
Начиная с Objective-C 2.0 (в OS X 10.5 «Leopard» и iOS) формальные протоколы теперь могут определять дополнительные методы , и класс соответствует протоколу, если он реализует все необходимые методы. Вы можете использовать ключевые слова @required
(по умолчанию) и, @optional
чтобы указать, должны или могут быть реализованы следующие объявления методов в соответствии с протоколом. (См. Раздел руководства по языку программирования Apple Objective-C 2.0, в котором обсуждаются дополнительные методы протокола .)
Дополнительные методы протокола открывают разработчикам большую гибкость, особенно для реализации делегатов и слушателей . Вместо того, чтобы расширять что-то вроде MouseInputAdapter (что может раздражать, поскольку Java также является одинарным наследованием) или реализовывать множество бессмысленных, пустых методов, вы можете принять протокол и реализовать только те необязательные методы, которые вам нужны. С помощью этого шаблона вызывающий проверяет, реализован ли метод перед его вызовом (используя -respondsToSelector ) следующим образом:
if ([myObject respondsToSelector:@selector(fillArray:withObject:)]) {
[myObject fillArray:anArray withObject:foo];
...
}
Если накладные расходы на отражение становятся проблемой, вы всегда можете кэшировать логический результат для повторного использования , но не поддавайтесь стремлению к преждевременной оптимизации. :-)
-conformsToProtocol:
вернет YES, только если класс явно принимает протокол. Вы хоть пробовали?
-conformsToProtocol:
действительно требуется, чтобы класс (или предок) официально объявил, что он принимает протокол. Не знаю, как я ошибся, спасибо за исправление!
Они почти идентичны. Однако одна вещь, которая меня уловила, заключается в том, что если вы явно не заявите, что объективный протокол C также реализует NSObject, ссылки на этот протокол не получают доступа к методам, которые объявляет NSObject (без предупреждения компилятора в любом случае). С java вы можете иметь ссылку на интерфейс и по-прежнему вызывать на нем toString () и т. Д.
например
Цель C:
@protocol MyProtocol
// Protocol definition
@end
id <MyProtocol> myProtocol;
[myProtocol retain] // Compiler warning
Ява:
public interface MyInterface {
// interface definition
}
MyInterface myInterface;
myInterface.toString(); // Works fine.
Цель C (фиксированная):
@protocol MyProtocol <NSObject>
// Protocol definition
@end
id <MyProtocol> myProtocol;
[myProtocol retain] // No Warning