@required だが定型的な処理を行うようなメソッドをプロトコルで定義すると、それを実装するクラスにコピペの嵐が発生しがちである:
// Assume FooProtocol has `@required -(void)fooMethod`.
@implementation FooableA // conforms to FooProtocol.
// Do something.
- (void)fooMethod {
[NSApp.delegate doSomething];
}
@end
@implementation FooableB // also conforms to FooProtocol.
// Do the same thing as FooableA#fooMethod. What a copy/paste hell.
- (void)fooMethod {
[NSApp.delegate doSomething];
}
@end
libextobjc ライブラリが提供する EXTConcreteProtocol を使うと、プロトコルのメソッドにデフォルトの実装を与えることができる:
FooProtocol.h
# import <libextobjc/EXTConcreteProtocol.h>
@protocol FooProtocol
@concrete
- (void)fooMethod;
@end
FooProtocol.m
# import "FooProtocol.h"
@concreteprotocol(FooProtocol)
// Default implementation for -(void)fooMethod.
- (void)fooMethod {
[NSApp.delegate doSomething];
}
@end
FooableA.h
# import "FooProtocol.h"
@interface FooableA : NSObject <FooProtocol>
@end
// Now an instance of FooableA can respond to fooMethod.
定義のしかたは見てのとおりで、デフォルト実装を与えたいメソッドを @concrete でマークする。メソッドの実装は @concreteprotocol(ProtocolName) ... @end の中に書く。
このプロトコルに適合したクラスはデフォルト実装のメソッドを使えるようになる。クラス内でデフォルトと同名のメソッドを定義すると、そちらが優先される。
**注意:**デフォルト実装の中では super にアクセスしてはならない。