Если метод протокола помечен @required, когда он не реализован, почему компилятор выдает предупреждение, а не ошибку? - PullRequest
6 голосов
/ 18 декабря 2011

Предположим, что:

  • Новый протокол объявлен
  • Метод в этом протоколе отмечен @required
  • Класс соответствует протоколу
  • Класс не реализует метод, указанный в Протоколе

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

Почему в этом случае компилятор выдает предупреждение, а не ошибку?

Ответы [ 5 ]

6 голосов
/ 18 декабря 2011

Ошибки выдаются только тогда, когда компилятор не может продолжить работу, потому что что-то пошло не так.

При вызове метода в Objective-C поиск метода выполняется во время выполнения, а не во время компиляции, как это делает C ++. В Objective-C «сообщение» просто отправляется объекту, что-то вроде obj.executeCommand("Hey, can you execute function <name> for me?"). В C ++ объект будет вызываться напрямую, как obj.<name>(). В случае Objective-C вызывается метод executeCommand (), который существует. В случае C ++ функция вызывается, но она не существует. Это методы, которые связаны на уровне компилятора, что означает, что они оба становятся адресами памяти, а не именами. executeCommand становится 0x12345678, но все еще использует то же сообщение ("execute function <name>").

Это, вероятно, очень запутанно, но это связано с тем, как методы реализуются на разных языках.

2 голосов
/ 18 декабря 2011

Если вы сильно к этому относитесь, почему бы не включить -Werror?

0 голосов
/ 10 августа 2016

Потому что бывают случаи, когда существуют фиктивные «требуемые» методы в плохо разработанном протоколе. Они должны были быть необязательными, но кто-то настоял, что они "обязательны". Таким образом, решение проблемы времени выполнения, а не ошибки компиляции, очень и очень разумно.

0 голосов
/ 21 декабря 2011

Objective-C - это динамический язык.Идея о том, что такое реализация, отличается от статического языка.
По большей части именно в коде, который большинство из нас реализует внутри блока @implementation ... @end.
Но что, если методне найден?Тогда у объекта есть шанс разобраться с ним динамически.

Представьте, что у вас есть интерфейс для проигрывателя звуковых эффектов:

@protocol FX  
- (void)playBeep;
- (void)playSiren;
- (void)playHonk;
@end

Реализация может воспроизводить файлы Beep.mp3, Siren.mp3, Honk.mp3, но вместо реализациикаждый из методов может переопределять -forwardInvocation: и анализировать строку селектора, например, псевдокод:

NSString *selName = NSStringFromSelector([invocation selector]);
if ([selName startsWith:@"play"]) {
  NSString filename = fileNameFromSelector(selName);
  [self playSoundFileNamed:filename];
}

Это может показаться надуманным, но как только вы начнете использовать динамические функцииязыка, вы начнете находить все больше и больше мест, где это имеет смысл.И в смысле, я имею в виду, помогает ли это усилие в долгосрочной перспективе?

В приведенном выше случае просто добавьте имя метода -sound * в интерфейс и вставьте имя с соответствующим именемзвуковой файлЭто просто работает.

Еще один пример из личных экспериментов: как работать с сущностями Core Data более естественным образом.Я хочу сделать это: NSArray * people = [Person findAllWithNameLike: @ "B%"];вместо того, чтобы разбираться с предикатами, получать запросы и т. д.
Но я не хочу определять каждую перестановку методов в коде.

Как насчет того, если бы я хотел построить XML-конструктор?Я бы посмотрел на динамический подход.Он хорошо послужил Groovy Builders (примеры приведены в Groovy / Grails).

Последний пример: у меня есть система признаков, где я могу определять поведение в форме групп методов, и мои объекты усваивают это поведение,Таким образом, хотя компилятор не видит реализацию интерфейса, которому соответствует мой объект, реализация внедряется в него из класса свойств с использованием среды выполнения Objective-C.Зачем мне это делать?Я нахожу, что многие методы делегатов являются базовыми, но в то же время отдельный базовый класс для каждой ситуации недостаточно гибок.Вместо вырезания и вставки из примеров кода мои «примеры» компилируются и запускаются :), а любые изменения отражаются во всех проектах с использованием этой черты.

Чтобы действительно понять, почему все это доступно вам, стоитиграть в среде Smalltalk (поиск Pharo или Squeak).Вот где Objective-C имеет свои корни.

И, наконец, чтобы прекратить эти предупреждения:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wprotocol"

@implementation ... @end

#pragma clang diagnostic pop
0 голосов
/ 18 декабря 2011

Я не знаю реального ответа, но вот пример использования, который пошел бы против него.

Что, если вы реализовали все методы протокола в категории ???Декларация основного интерфейса принимает протокол, однако реализация метода протокола относится к категории.Это допустимый код, но он покажет ошибку компиляции, если компилятор был таким строгим !!

...