Как избежать предупреждения "неполной реализации" в частичном базовом классе

Я создал протокол, который мои классы должны реализовать, а затем учесть некоторые общие функции в базовый класс, поэтому я сделал это:

@protocol MyProtocol
- (void) foo;
- (void) bar;
@end

@interface Base <MyProtocol>
@end

@interface Derived_1 : Base
@end

@interface Derived_2 : Base
@end

@implementation Base
- (void) foo{
//something foo
}
@end

@implementation Derived_1
- (void) bar{
//something bar 1
}
@end

@implementation Derived_2
- (void) bar{
//something bar 2
}
@end

Таким образом, в моем коде я использую общий идентификатор <MyProtocol> .

Код работает (до тех пор, пока Base не используется напрямую), но компилятор задыхается в конце реализации Base с предупреждением:

Incomplete implementation of class Base

Есть ли способ избежать этого предупреждения или, что еще лучше, более правильный способ получить это частично реализованное поведение абстрактного базового класса в Objc?

Ответы

Ответ 1

Вы могли бы сделать что-то вроде этого:

@implementation Base

- (void)bar
{
    if ([self class] == [Base class]) {
        [self doesNotRecognizeSelector:_cmd];
    }
}

@end

Таким образом, у вас есть реализация, но по умолчанию она вызывает исключение. Однако, если производный класс случайно вызывает [super bar] или не переопределяет bar, то исключение не будет повышаться. Если это не то, что вы хотите, вы можете просто сократить его до:

@implementation Base

- (void)bar
{
    [self doesNotRecognizeSelector:_cmd];
}

@end

В этом случае возникает исключение, даже если подкласс вызывает [super bar] или не переопределяет bar.

Ответ 2

В определении протокола вам необходимо объявить свои методы под ключевым словом @optional.

Ваш код должен выглядеть так:

@protocol MyProtocol

@optional
- (void) foo;
- (void) bar;

@end

Смотрите question на SO.

Ответ 3

В Obj-C нет понятия абстрактного класса. Таким образом, вы не можете позволить вашему базовому классу быть абстрактным (что означает, что "не" реализует все методы в протоколе). У вас может быть только 2 варианта. Пусть метод в протоколе будет optionol, а затем реализует его самостоятельно в производном классе. Или, заставляйте все классы в иерархии реализовывать его, но позвольте вызывающему абоненту быть осторожным, чтобы не вызывать неправильные методы

Ответ 4

Я делаю что-то вроде этого

@protocol MyProtocol
- (void) foo;
- (void) bar;
@end

@interface BaseAbstract
- (void) bar; // give a default implementation
@end

@interface Derived_1 : BaseAbstract<MyProtocol>
// you will get a compiler warning for foo() since it is not implemented

// you will NOT get compiler for bar() warning since a default 
// implementation is inherited
@end

@interface Derived_2 : BaseAbstract<MyProtocol>
@end

typedef BaseAbstract<MyProtocol> Base;