2013/06/16

[obc]@protocolはpure virtualみたいなものか?

ちょっと説明を読んだだけなのだが、@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 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。