Objective C Указатель на класс, который реализует протокол - PullRequest
7 голосов
/ 19 апреля 2010

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

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

Какой-то псевдокод, если это не имеет смысла:

@interface superclass: NSObject
{}

@interface child1: superclass<MyProtocol>
{}

@interface child2: superclass<MyProtocol>
{}

Потребитель этих классов:

@class child1
@class child2
@class superclass

@interface SomeViewController: UIViewController
{
    child1 *oneView;
    child2 *otherView;
    superclass *currentView;
}

-(void) someMethod
{
    [currentView protocolFunction];
}

Единственный хороший способ, с помощью которого я обнаружил выполнение чисто виртуальных функций в Objective-C, - это взлом, добавив [self doesNotRecognizeSelector:_cmd]; в родительский класс, но это не идеально, так как это вызовет ошибки времени выполнения, а не время компиляции.

Ответы [ 4 ]

11 голосов
/ 19 апреля 2010

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

- (void)someMethod
{
    // See if the object in currentView conforms to MyProtocol
    //
    if ([currentView conformsToProtocol:@protocol(MyProtocol)])
    {
        // Cast currentView to the protocol, since we checked to make
        // sure it conforms to it. This keeps the compiler happy.
        //
        [(SuperClass<MyProtocol> *) currentView protocolMethod];
    }
}
5 голосов
/ 19 апреля 2010

Мне удалось заставить компилятор правильно предупреждать меня, сделав свойство superclass *currentView похожим на это:

@property (nonatomic, retain) superclass<MyProtocol> *currentView;
3 голосов
/ 19 апреля 2010

В качестве альтернативы вы можете использовать следующее

if ([unknownObject conformsToProtocol:@protocol(MyProtocol)])
   [unknownObject performSelector:@selector(methodInProtocol)];

вместо следующего, если вы просто хотите подавить предупреждение.

if ([unknownObject conformsToProtocol:@protocol(MyProtocol)])
   [unknownObject methodInProtocol];  // will cause warning

executeSelector: будет работать, только если число аргументов равно нулю или единице. Более гибкие вызовы могут быть достигнуты с помощью NSInvocation.

1 голос
/ 19 апреля 2010

Лично я бы реализовал протокол на суперклассе, но реализовал бы методы, подобные этому:

- (id) myProtocolMethod {
  NSAssert(NO, [NSString stringWithFormat:@"-[%@ %@] must be overridden", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]);
  return nil;
}

Таким образом, если вы когда-нибудь забудете переопределить метод в конкретном подклассе, это должно быть сразу очевидно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...