ちょっと説明を読んだだけなのだが、@protocolはC++でいうところのpure virtualなメンバ関数みたいなものじゃなかろうか、と思った。
「継承したらこいつらは必ず実装しろよー」というやつだ。
//[0.h]
#import <Foundation/Foundation.h>@protocol AddrBook- (NSString *)name;- (NSInteger)age;@end--------------------//[1.h]
#import "0.h"
@interface HellBook : NSObject <AddrBook>@end--------------------//[1.m]
#import <stdio.h>#import "1.h"
@interface HellBook() {NSString *myName;NSInteger myAge;}@end@implementation HellBook- (id)init{myName = @"Black Dog";
myAge = 3000;return self;
}- (NSString *)name{return myName;
}- (NSInteger)age{return myAge;
}@end------------------------//[main.m]
#import <Foundation/Foundation.h>#import "1.h"
int main(void){HellBook *hb = [[HellBook alloc] init];NSLog(@"%@ - %ld\n", [hb name], [hb age]);
return 0;
}
$ clang -o tst 1.m main.m -lobjc -framework Cocoa
$ ./tst
2013-06-16 17:40:09.364 tst[395:707] Black Dog - 3000
うーん・・・。
なんだかよくわからない・・・。
pure virtualなclassは、しょせんclassなので実装も書くことができる。
インスタンスは作れないけど、ポインタ変数としては使うことができる。
それに対して、@protocolはポインタ変数も作ることができない。
AddrBook *hb;
こういうことをしたいなら、こうやる。
id<AddrBook> hb;
と思ったのだが・・・、これはこれでうまくいくけど、<AddrBook>がなくてもうまくいく。
しかも、id型じゃなくてid*型にしてもうまくいってしまった(warning多数だが)。
<AddrBook>みたいなのを付けるメリットとしては、id型だと何でも受け入れてしまうけど、id<プロトコル>とすることで、該当するプロトコルを持ったインスタンスしか代入できなくなる、というところか。
間違えの防止に役立つんですかね。
でも、id型の変数を代入する処理にしたが、これは怒られない。
ってことは、動的エラーになる可能性があると言うことか(NSInvalidArgumentException例外が発生するみたい)。
void func(id val)
{
id<AddrBook> hb = val;
}
うーん、なんか本質をつかんでないなあ。
もう少し資料を読まねばならぬようだ。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。