#objective-c #protocols
#objective-c #протоколы
Вопрос:
У меня есть протокол, подобный этому:
@protocol ProfileSubObjects <NSObject, NSCoding>
@required
- (BOOL) hasGraph;
@optional
- (NSArray *) xGraphValues;
- (NSArray *) yGraphValues;
Я хочу сделать обязательными эти два необязательных метода, если значение hasGraph равно YES.
Возможно ли это?
Комментарии:
1. Чего вы пытаетесь достичь этим?
Ответ №1:
Нет. Методы либо требуются протоколом, либо нет. Во-первых, значение -hasGraph неизвестно во время компиляции. Поскольку это метод экземпляра, а не метод класса, он даже не известен во время выполнения, пока вы не создадите конкретный объект. Кроме того, объект может сообщать разные значения для -hasGraph в разное время.
Лучшее, что можно сделать здесь, это просто задокументировать тот факт, что если -hasGraph возвращает YES, ожидается, что значения -xGraphValues и -yGraphValues будут реализованы. Вы могли бы обеспечить это, создав исключение, или вы могли бы изящно выполнить сбой и просто не извлекать никаких данных, если эти методы не реализованы. Используйте -RESPONSESTOSELECTOR: метод, чтобы проверить, реализован ли метод перед его вызовом.
Ответ №2:
Нет, это невозможно. По крайней мере, не так. Однако существует более глубокая проблема. Вопрос предполагает рассмотрение проверки компиляции в сравнении с runtime и объектной ориентацией.
Пометка чего-либо как @optional или @required означает, что вы хотите выполнить проверку во время компиляции того, соответствуют ли эти объекты контракту протокола о предоставлении реализаций — или нет, в случае @optional — этих методов.
Следовательно, нет причин, чтобы проверка во время компиляции зависела от значения переменной времени выполнения, в данном случае hasGraph.
Лучшим подходом было бы использовать проверку сообщений Responsestoselector. В качестве альтернативы у вас мог бы быть подкласс, который имеет график и предоставляет значения графиков x и y.
Ответ №3:
Это невозможно; результат hasGraph будет известен только во время выполнения, тогда как обязательные / необязательные части протокола используются компилятором для проверки во время компиляции.
Что вы, вероятно, хотите сделать, так это добавить сильное примечание о том, что если hasGraph возвращает YES, то должны быть реализованы xGraphValues и yGraphValues, что привнесет немного неформальности в ваш официальный протокол. Вы всегда можете сделать что-то вроде:
if([object respondsToSelector:@selector(xGraphValues)] amp;amp;
[object respondsToSelector:@selector(yGraphValues)])
Для проверки во время выполнения, реализует ли объект части протокола, которые вам нужны, чтобы иметь возможность выполнять с ним определенную операцию. Вероятно, было бы разумно поместить этот материал в NSAssert, если вы хотите, чтобы кто-то, кто реализует несоответствующий объект, мог выяснить, что они сделали неправильно, с помощью отладочной сборки.