objective-C中的Class(類類型),Selector(選擇器SEL),函數(shù)指針(IMP)

objective-C中的Class(類類型),Selector(選擇器SEL),函數(shù)指針(IMP)

今天在園子里看到了一篇牛文“Objective-C 2.0 with Cocoa Foundation--- 5见咒,Class類型额嘿,選擇器Selector以及函數(shù)指針 ”畔柔,講得十分精彩赂弓,忍不住把它的代碼加上注釋整理于此忌堂,以便日后查看描验。
個(gè)人體會(huì):obj-C中的“Class類型變量”比c#中的Object基類還要靈活占哟,可以用它生成任何類型的實(shí)例(但是它又不是NSObject)。而選擇器SEL與函數(shù)指針I(yè)MP翩迈,如果非要跟c#扯上關(guān)系的話持灰,這二個(gè)結(jié)合起來,就點(diǎn)類似c#中的反射+委托负饲,可以根據(jù)一個(gè)方法名稱字符串堤魁,直接調(diào)用方法。
"牛"的基類 Cattle.h
1
2
3
4
5
6
7
8

import <Foundation/Foundation.h>

@interface Cattle : NSObject {
int legsCount;
}

  • (void)saySomething;
  • (void)setLegsCount:(int) count;
    @end
    Cattle.m
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

import "Cattle.h"

@implementation Cattle

-(void) saySomething
{
NSLog(@"Hello, I am a cattle, I have %d legs.", legsCount);
}

-(void) setLegsCount:(int) count
{
legsCount = count;
}
@end
子類“公牛" Bull.h
1
2
3
4
5
6
7
8
9
10

import <Foundation/Foundation.h>

import "Cattle.h"

@interface Bull : Cattle {
NSString *skinColor;
}

  • (void)saySomething;
  • (NSString*) getSkinColor;
  • (void) setSkinColor:(NSString *) color;
    @end
    Bull.m
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

import "Bull.h"

@implementation Bull

-(void) saySomething
{
NSLog(@"Hello, I am a %@ bull, I have %d legs.", [self getSkinColor],legsCount);
}

-(NSString*) getSkinColor
{
return skinColor;
}

  • (void) setSkinColor:(NSString *) color
    {
    skinColor = color;
    }
    @end
    代理類DoProxy.h (關(guān)鍵的代碼都在這里)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

import <Foundation/Foundation.h>

//定義幾個(gè)字符串常量

define SET_SKIN_COLOR @"setSkinColor:"

define BULL_CLASS @"Bull"

define CATTLE_CLASS @"Cattle"

@interface DoProxy : NSObject {
BOOL notFirstRun;

id cattle[3];
//定義二個(gè)選擇器
SEL say;
SEL skin;
 
//定義一個(gè)函數(shù)指針(傳統(tǒng)C語言的處理方式)
void(*setSkinColor_Func)(id,SEL,NSString*);
 
//定義一個(gè)IMP方式的函數(shù)指針(obj-C中推薦的方式)
IMP say_Func;
 
//定義一個(gè)類
Class bullClass;

}

-(void) doWithCattleId:(id) aCattle colorParam:(NSString*) color;
-(void) setAllIVars;
-(void) SELFuncs;
-(void) functionPointers;

@end
DoProxy.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

import "DoProxy.h"

import "Cattle.h"

import "Bull.h"

@implementation DoProxy

//初始化所有變量

  • (void) setAllIVars
    {
    cattle[0] = [Cattle new];

    bullClass = NSClassFromString(BULL_CLASS);
    //即cattle[1],cattle[2]都是Bull類的實(shí)例
    cattle[1] = [bullClass new];
    cattle[2] = [bullClass new];

    say = @selector(saySomething);
    skin = NSSelectorFromString(SET_SKIN_COLOR);
    }

//初始化id

  • (void) doWithCattleId:(id) aCattle colorParam:(NSString*) color
    {
    //第一次運(yùn)行的時(shí)候
    if(notFirstRun == NO)
    {
    NSString *myName = NSStringFromSelector(_cmd);//取得當(dāng)前正在執(zhí)行的方法的名字
    NSLog(@"Running in the method of %@", myName);
    notFirstRun = YES;//修改初次運(yùn)行標(biāo)志位
    }

    NSString *cattleParamClassName = [aCattle className];//取得aCattle的"類名稱"

    //如果aCattle是Bull或Cattle類的實(shí)例
    if([cattleParamClassName isEqualToString:BULL_CLASS] || [cattleParamClassName isEqualToString:CATTLE_CLASS])
    {
    [aCattle setLegsCount:4];//設(shè)置牛的4條腿
    if([aCattle respondsToSelector:skin])//如果aCattle對應(yīng)的是類中,有定義方法"setSkinColor"
    {
    [aCattle performSelector:skin withObject:color];//則調(diào)用setSkinColor方法
    }
    else
    {
    NSLog(@"Hi, I am a %@, have not setSkinColor!", cattleParamClassName);//否則輸出相應(yīng)的提示信息
    }
    [aCattle performSelector:say];//最后執(zhí)行saySomething方法(這二個(gè)方法在Bull與Cattle類中都有,所以肯定能運(yùn)行)
    }
    else //如果aCattle即不是Bull類也不是Cattle類的實(shí)例
    {
    NSString *yourClassName = [aCattle className];
    NSLog(@"Hi, you are a %@, but I like cattle or bull!", yourClassName);//顯示這個(gè)"異類"的相關(guān)信息
    }
    }

//初始化選擇器以及相應(yīng)函數(shù)

  • (void) SELFuncs
    {
    [self doWithCattleId:cattle[0] colorParam:@"brown"];
    [self doWithCattleId:cattle[1] colorParam:@"red"];
    [self doWithCattleId:cattle[2] colorParam:@"black"];
    [self doWithCattleId:self colorParam:@"haha"];//這里故意傳入一個(gè)異類self(即DoProxy本身),DoProxy當(dāng)然不是Bull或Cattle
    }

//函數(shù)指針測試

  • (void) functionPointers
    {
    //取得函數(shù)指針的第一種方式
    setSkinColor_Func=(void ()(id, SEL, NSString)) [cattle[1] methodForSelector:skin];
    //上面的語句其實(shí)等效于下面這種方法
    //IMP setSkinColor_Func = [cattle[1] methodForSelector:skin];

    //用第二種方法取得saySomething的函數(shù)指針
    say_Func = [cattle[1] methodForSelector:say];

    //用函數(shù)指針的形式調(diào)用setSkinColor
    setSkinColor_Func(cattle[1],skin,@"verbose");

    NSLog(@"Running as a function pointer will be more efficiency!");

    //調(diào)用saySomething方法
    say_Func(cattle[1],say);
    }

@end
測試主函數(shù)main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

import <Foundation/Foundation.h>

import "DoProxy.h"

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
DoProxy *doProxy = [DoProxy new];

[doProxy setAllIVars];
[doProxy SELFuncs];
[doProxy functionPointers];
 
[doProxy release];
[pool drain];
return 0;

}
運(yùn)行結(jié)果:

2011-02-28 21:40:33.240 HelloSelector[630:a0f] Running in the method of doWithCattleId:colorParam:
2011-02-28 21:40:33.245 HelloSelector[630:a0f] Hi, I am a Cattle, have not setSkinColor!
2011-02-28 21:40:33.247 HelloSelector[630:a0f] Hello, I am a cattle, I have 4 legs.
2011-02-28 21:40:33.248 HelloSelector[630:a0f] Hello, I am a red bull, I have 4 legs.
2011-02-28 21:40:33.250 HelloSelector[630:a0f] Hello, I am a black bull, I have 4 legs.
2011-02-28 21:40:33.251 HelloSelector[630:a0f] Hi, you are a DoProxy, but I like cattle or bull!
2011-02-28 21:40:33.252 HelloSelector[630:a0f] Running as a function pointer will be more efficiency!
2011-02-28 21:40:33.254 HelloSelector[630:a0f] Hello, I am a verbose bull, I have 4 legs.

作者:菩提樹下的楊過
出處:http://yjmyzz.cnblogs.com
本文版權(quán)歸作者和博客園共有返十,歡迎轉(zhuǎn)載妥泉,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接洞坑,否則保留追究法律責(zé)任的權(quán)利盲链。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市迟杂,隨后出現(xiàn)的幾起案子刽沾,更是在濱河造成了極大的恐慌,老刑警劉巖排拷,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侧漓,死亡現(xiàn)場離奇詭異,居然都是意外死亡监氢,警方通過查閱死者的電腦和手機(jī)布蔗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浪腐,“玉大人何鸡,你說我怎么就攤上這事∨;叮” “怎么了骡男?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長傍睹。 經(jīng)常有香客問我隔盛,道長犹菱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任吮炕,我火速辦了婚禮腊脱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘龙亲。我一直安慰自己陕凹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布鳄炉。 她就那樣靜靜地躺著杜耙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拂盯。 梳的紋絲不亂的頭發(fā)上佑女,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音谈竿,去河邊找鬼团驱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛空凸,可吹牛的內(nèi)容都是我干的嚎花。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼呀洲,長吁一口氣:“原來是場噩夢啊……” “哼紊选!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起两嘴,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤翰苫,失蹤者是張志新(化名)和其女友劉穎嗽冒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體金顿,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡仿荆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年贰您,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拢操。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锦亦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出令境,到底是詐尸還是另有隱情杠园,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布舔庶,位于F島的核電站抛蚁,受9級(jí)特大地震影響陈醒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瞧甩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一钉跷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肚逸,春花似錦爷辙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至思灰,卻和暖如春玷犹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背洒疚。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工歹颓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人油湖。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓巍扛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親乏德。 傳聞我的和親對象是個(gè)殘疾皇子撤奸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容