Я знаю 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
Java:
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