Определение условий в протоколах

#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, если вы хотите, чтобы кто-то, кто реализует несоответствующий объект, мог выяснить, что они сделали неправильно, с помощью отладочной сборки.