Object C學習筆記17-動態判斷和選擇器

  當時學習Object C的時被人鄙視了一頓,說使用.NET的思想來學Object C就是狗屎;不過也挺感謝這位仁兄的,這讓我學習的時候更加的謹慎。今天的學習筆記主要記錄Object C中的動態類型相關內容。html

  首先仍是和.NET先對比一下,.NET中存在一個關鍵字var ,這個估計用過.NET的都知道,除非沒有接觸過3.0以上版本的。在.NET中可以使用var來聲明任何類型的局部變量,負責告訴編譯器,該變量須要根據初始化表達式來推斷變量的類型,並且只能是局部變量.可是這裏要注意的時var 並非一個新的類型,只是一個關鍵字而已,在定義參數和返回值的時候都不能使用var.ide

  在.net中還有一個類型dynamic,表示變量的類型在運行時決定,也就是在運行此代碼的時候纔去校驗類型是否符合等,若是類型不符則會拋出異常。而var則會在編譯的過程就可以發現類型是否準確。學習

  在這裏咱們要說Object C中的id類型 和 var 以及 dynamic 有什麼區別?測試

 

  一. Object C中的id類型atom

    在Objective-C 中,id 類型是一個獨特的數據類型。在概念上能夠轉換爲任何數據類型。換句話說,id 類型的變量能夠存聽任何數據類型的對象。在內部處理上,這種類型被定義爲指向對象的指針,其實是一個指向這種對象的實例變量的指針。spa

    先看一段代碼瞭解一下id類型的時候:.net

id stu=[[Student alloc] init];
[stu eat];
        
id per=[[Person alloc] init];
[per eat];

    以上代碼分別用建立了兩個類Student 和 Person的實例,類型都是使用的id,而且調用了其相應的方法,成功運行。指針

 

  二. 動態判斷code

    在Object C中如何判斷某個類實例是不是某個類的子類,某個類中是否包含某個方法。這個要求彷佛和.NET中的反射有點相似,的確在Object中一樣提供了相似的方法來動態判斷。orm

    咱們先定義一個父類:

#import <Foundation/Foundation.h>

@interface Person : NSObject{
    NSString *name;
    int age;
    NSString *address;
}
@property (nonatomic,retain) NSString *name;
@property (nonatomic,assign) int age;
@property (nonatomic,retain) NSString *address;

-(void) eat;

-(void) speak;

-(void) write;

-(Person *) getPerson;

-(id) getString;

+(void) Info;

@end

----------------------------------------------------------------
#import "Person.h"

@implementation Person

@synthesize name;
@synthesize age;
@synthesize address;

-(void) eat{
    NSLog(@"Person.eat()");
}

-(void) speak{
    NSLog(@"Person.speak()");
}

-(void) write{
    NSLog(@"Person.write()");
}

-(Person *) getPerson{
    Person *p=[[Person alloc] init];
    p.name=@"li";
    p.age=25;
    p.address=@"上海";
    return p;
}

-(id) getString{
    Person *p=[[Person alloc] init];
    p.name=@"lin";
    p.age=22;
    p.address=@"北京";
    return p;
}

+(void) Info{
    NSLog(@"Person.Info");
}

@end
Person 類

    而後定義一個子類,用於繼承Person類。

#import "Student.h"

@implementation Student

@end
Student 類

    Student類繼承了Person類,說明Student類擁有了Person類的全部方法和屬性

    (1) isMemberOfClass 用於判斷是不是某個類的實例

bool flag1=[stu isMemberOfClass:[Student class]];
NSLog(@"%d",flag1);
bool flag2=[stu isMemberOfClass:[Person class]];
NSLog(@"%d",flag2);

    上面的代碼 flag1 爲yes,而flag2爲no,說明stu是Student類的實例,Student爲Person的子類,可是不能判斷爲Person的實例。

    (2) isKindOfClass 判斷是否爲某個類的實例或者某個類子類的實例

bool flag1=[stu isKindOfClass:[Student class]];
NSLog(@"%d",flag1);
bool flag2=[stu isKindOfClass:[Person class]];
NSLog(@"%d",flag2);

    由於Student是Person的子類,因此上面flag1,flag2 的都爲YES

    (3) respondsToSelector 用於判斷某個類型或者對象是否有能力迴應(調用)指定的方法

bool flag3=[per respondsToSelector:@selector(eat)];
        NSLog(@"%d",flag3);
        
        bool flag4=[stu respondsToSelector:@selector(eat)];
        NSLog(@"%d",flag4);
        
        bool flag5=[per respondsToSelector:@selector(Info)];
        NSLog(@"%d",flag5);
        
        bool flag6=[Person respondsToSelector:@selector(Info)];
        NSLog(@"%d",flag6);
respondsToSelector 測試代碼

    上面的代碼測試輸出結果以下:

2014-03-22 20:28:09.778 ObjectSelect[11321:303] 1
2014-03-22 20:28:09.778 ObjectSelect[11321:303] 1
2014-03-22 20:28:09.778 ObjectSelect[11321:303] 0
2014-03-22 20:28:09.779 ObjectSelect[11321:303] 1

    第一個和第二個方法的調用都返回1,說明其有能力迴應(調用)方法eat, 關鍵看第三個和第四個方法的調用,返回0,1 說明實例和對象的調用是不同的,而Info方法是一個全局方法 ,用 "+" 標識的方法就是全局方法,至關於靜態方法。第3個方法是使用實例來調用的返回0,說明對象實例是沒有能力調用靜態方法的。

     (4) instancesRespondToSelector 用於判斷某個對象的實例是否有能力迴應(調用)指定的方法

        bool flag7=[Person instancesRespondToSelector:@selector(eat)];
        NSLog(@"%d",flag7);
        bool flag8=[Person instancesRespondToSelector:@selector(Info)];
        NSLog(@"%d",flag8);

    上面的測試代碼輸出結果以下:

2014-03-22 20:39:04.700 ObjectSelect[11344:303] 1
2014-03-22 20:39:04.700 ObjectSelect[11344:303] 0

    第一個方法調用返回1,說明Person的實例能夠調用eat方法,第二個方法返回0,說明Person的實例不能夠調用Info方法。

 

  三. 如何動態調用方法

    上面已經說到了,任何一個對象的實例咱們均可以使用id來指向其地址,這是一個動態的類型那麼如何調用其具體的方法。

[stu performSelector:@selector(eat)];
[Person performSelector:@selector(Info)];

    使用performSelector 方法能夠動態的調用其方法,若是是實例方法則調用的須要使用對象實例,而調用靜態方法這須要使用對象自己。

    上面的辦法調用都是沒有參數的,那麼如何調用有輸入參數的方法呢?

[stu performSelector:@selector(speak:) withObject:@"ddddd"];
        
[stu performSelector:@selector(write:andAge:) withObject:@"fasdfadaf" withObject:@"333"];

    使用withObject 來填充參數.可是這個方法的調用有點不足的地方,若是有多個參數輸入參數就有問題。 這個地方尚未徹底沒有弄清楚,有待後續研究。若是真的涉及到多個參數,那麼可使用對象封裝好這些參數或者將參數存入一個集合中傳遞輸入。

 

  四. 總結

    這篇主要講到了動態類型id,以及其如何使用。還有關於類的動態判斷以及選擇器。但都只是比較粗略的介紹了,後面的學習中繼續深刻研究。

    本文開頭的時候對比了.NET 中的var , dynamic 。 從上面的文章介紹,那麼Object C中的id 和 .NET中的哪一個關鍵字比較像,我的的學習體會和dynamic比較相似,若有不對的正確的地方請高手斧正!

 

  補充說明文章: Object C學習筆記18-SEL,@ selector,Class,@class

  本文到此結束,請高手勿噴,菜鳥的學習須要鼓勵!

相關文章
相關標籤/搜索