Протоколы Objective C, требующие реализации по крайней мере одного из набора методов - PullRequest
7 голосов
/ 06 ноября 2011

В Задаче C могут потребоваться или необязательны методы протокола:

@protocol AProtocol

@required
-(void) aRequiredMethod;

@optional
-(void) anOptionalMethod;

@end

Есть ли элегантный способ сказать, что объект, соответствующий протоколу, должен реагировать хотя бы на один из набора методов, моя мечта была бы что-то вроде

@protocol AProtocol

@anyof
-(void) onePossibleMethod;
-(void) anotherPossibleMethod;

@optional
-(void) anOptionalMethod;

@end

EDIT:

Это (насколько я знаю) невозможно, если бы был способ вызвать предупреждение о времени компиляции, если бы класс, объявленный как соответствующий данному протоколу, состоял полностью из дополнительных методов

@protocol AProtocol

@optional
-(void) onePossibleMethod;
-(void) anotherPossibleMethod;

@end

не удалось реализовать хотя бы один из них.

Ответы [ 3 ]

3 голосов
/ 06 ноября 2011

Ну, вы работаете с ObjC, поэтому вам нужно проявить некоторую сдержанность:

@protocol MONAbstractDataProvider
@optional
- (void)anOptionalMethod;
@end

@protocol MONDataProviderA < MONAbstractProvider >
@required
- (void)onePossibleMethod;
@end

@protocol MONDataProviderB < MONAbstractProvider >
@required
- (void)anotherPossibleMethod;
@end

В этом случае вам придется выполнить тест confromsToProtocol: на месте вызова, а не тест respondsToSelector: для onePossibleMethod и anotherPossibleMethod. Тогда вы передаете MONAbstractDataProvider вокруг. Это может ввести некоторую безопасность типов, если вы помните правила, но на самом деле это лишь немного лучше, чем обычный подход.

Таким образом, сторона клиента будет выглядеть так:

- (void)update:(NSObject<MONAbstractDataProvider>*)provider
{
    if ([provider conformsToProtocol:@protocol(MONDataProviderA)]) {
        [(NSObject<MONDataProviderA>*)protocol onePossibleMethod];
    }
    else if ([provider conformsToProtocol:@protocol(MONDataProviderB)]) {
        [(NSObject<MONDataProviderB>*)provider anotherPossibleMethod];
    }
    else {
        assert(0 && "rule broken");
    }
}

Это, конечно, предполагает, что клиент знает обо всех производных.

Вместо этого вы можете предпочесть более простой единый подход, если они оба void:

@protocol MONAbstractDataProvider
@required
- (void)performPossibleMethod;
@optional
- (void)anOptionalMethod;
@end
3 голосов
/ 07 ноября 2011

Нет хорошего способа выразить это в Objective-C. Если вы должны это сделать, IMO самый идиоматичный и наименее вздутый код - что-то вроде этого:

@protocol AProtocol

@required
- (SEL)methodToUse; // returns one of "onePossibleMethod" or "anotherPossibleMethod"

@optional
-(void) onePossibleMethod;
-(void) anotherPossibleMethod;
-(void) anOptionalMethod;

@en
0 голосов
/ 06 ноября 2011

У вас может быть свойство динамического делегата, которое позволяет делегату назначаться только классам, которые реализуют один или другой метод, но это происходит во время выполнения, а не во время компиляции.Вы также можете создать bash-скрипт, который бы проверял, реализован ли тот или другой, и это было бы во время компиляции.

...