標籤:動態類型檢測 回應程式法
———————————————————————————————————————————
動態類型檢測
代碼:
#import <Foundation/Foundation.h>
@interface Animal : NSObject
-(void)run;
-(void)abc;
@end
@implementation Animal
-(void)run
{
NSLog(@"Animal run!");
}
-(void)abc
{
NSLog(@"abc!");
}
@end
@interface Dog : Animal
-(void)run;
-(void)eat;
-(void)bark;
@end
@implementation Dog
-(void)run
{
NSLog(@"Dog run!");
}
-(void)eat
{
NSLog(@"Dog eat!");
}
-(void)bark
{
NSLog(@"Dog bark!");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
//動態類型檢測:
//*******************************************************
// 1)判斷某個對象是否是該類的執行個體對象,或者是其子類的執行個體對象(對象和類)
// isKindOfClass使用格式: [對象 isKindOfClass:類對象];
Animal *ani=[Animal new];
//BOOL isIstance=[ani isKindOfClass:[ani class]];
BOOL isInstance=[ani isKindOfClass:[Animal class]];
//上面兩種寫法都行,因為可以用 類類型的執行個體對象/類名 去調用類對象
NSLog(@"isInstance = %d",isInstance);//輸出是1(ani本來就是Animal的執行個體對象,自然為1)
Dog *dog=[Dog new];
BOOL isInstance1=[dog isKindOfClass:[Animal class]];
NSLog(@"isIstance1 = %d",isInstance1);//輸出是1(Dog是Animal的子類,dog是Dog的執行個體對象,自然為1)
Person *p=[Person new];
BOOL isInstance2=[p isKindOfClass:[Animal class]];
NSLog(@"isInstance2 = %d",isInstance2);//輸出是0(Person是無關的類,不是Animal的子類,p是Person的執行個體對象,所以為0)
//*******************************************************
// 2)判斷某個對象是否是該類的執行個體對象(單指這個類,不包括其子類)
// isMemberOfClass使用格式: [對象 isMemberOfClass:類對象];
BOOL isInstance3=[ani isMemberOfClass:[Animal class]];
NSLog(@"isInstance3 = %d",isInstance3);//輸出是1(ani是Animal的執行個體對象,自然為1)
BOOL isInstance4=[dog isMemberOfClass:[Animal class]];
NSLog(@"isInstance4 = %d",isInstance4);//輸出是0(dog是Dog的執行個體對象,Dog是Animal的子類,所以為0)
//*******************************************************
// 3)判斷某個類是不是另一個類的子類
// isSubclassOfClass使用格式: [類名/類對象 isSubclassOfClass:類對象];
BOOL isInstance5=[Dog isSubclassOfClass:[Animal class]];
NSLog(@"isInstance5 = %d",isInstance5);//輸出為1(Dog是Animal的子類)
BOOL isInstance6=[Animal isSubclassOfClass:[Dog class]];
NSLog(@"isInstance6 = %d",isInstance6);//輸出為0(Animal是Dog的父類)
BOOL isInstance7=[[Dog class] isSubclassOfClass:[Animal class]];
NSLog(@"isInstance7 = %d",isInstance7);//輸出為1(這裡注意前面可以寫作類對象的形式)
// BOOL isInstance8=[[Dog class] isSubclassOfClass:Animal];//這句話編譯不會通過,因為後面Animal不是類對象的格式
//*******************************************************
// 4)判斷對象能否響應指定的方法
// respondsToSelector使用格式: [對象 respondsToSelector:方法的SEL];
// BOOL isRespond1=ani respondsToSelector:<#(SEL)#>//這裡顯然參數傳進來的應該是一個SEL的類型
// 我們一起來回顧一下SEL是什麼。首先SEL表示方法的儲存位置,我們一般先將方法封裝為SEL類型,然後根據sel資料找到方法的地址,然後根據方法地址調用相應的方法。所以接下來我們應該這樣處理:
SEL [email protected](eat);//先將資料封裝成SEL類型,獲得方法的地址
BOOL isRespond1=[dog respondsToSelector:s1];//eat是Dog裡面的方法,dog是Dog的執行個體對象,所以可以訪問
NSLog(@"isRespond1 = %d",isRespond1);//輸出為1
SEL [email protected](bark);
BOOL isRespond2=[ani respondsToSelector:s2];//ani是Animal的執行個體對象,但是bark是Dog的特有方法,所以說無法訪問
NSLog(@"isRespond = %d",isRespond2);//輸出為0
// 所以說我們一般用執行個體對象調用方法之前,可以先作一個判斷,如下:
// if(isRespond1)
// {
// [dog eat];
// }
// else
// {
// NSLog(@"無法調用");
// }
// 這樣可以把錯誤扼殺在編譯時間,而不是到了啟動並執行時候錯誤才發現。
//*******************************************************
// 5)判斷類能否調用(相應)指定的方法
BOOL isRespond3=[Dog instancesRespondToSelector:s1];//s1是eat的SEL封裝,eat是Dog的方法,所以可以調用
NSLog(@"isRespond3 = %d",isRespond3);//輸出為1
BOOL isRespond4=[Animal instancesRespondToSelector:s1];//顯然Animal不能調用其子類特有的方法
NSLog(@"isRespond4 = %d",isRespond4);//輸出為0
SEL [email protected](abc);//abc方法是Animal中的
BOOL isRespond5=[Dog instancesRespondToSelector:s3];//子類繼承父類的abc方法,自然子類可以調用(★這裡我要說明一點,如果你在父類中唯寫了abc方法的聲明,而沒有寫實現的話,這裡結果就是0,表示無法調用★)
NSLog(@"isRespond5 = %d",isRespond5);//輸出為1
//*******************************************************
}
return 0;
}
———————————————————————————————————————————
回應程式法(屬於動態類型檢測部分)
#import <Foundation/Foundation.h>
@interface Animal : NSObject
-(void)run;
@end
@implementation Animal
-(void)run
{
NSLog(@"Animal run!");
}
@end
@interface Dog : Animal
-(void)eat:(NSString *)foodName;
-(void)eat:(NSString *)foodName andDogName:(NSString *)dogName;
@end
@implementation Dog
-(void)eat:(NSString *)foodName
{
NSLog(@"Dog eat %@",foodName);
}
-(void)eat:(NSString *)foodName andDogName:(NSString *)dogName
{
NSLog(@"%@ eat %@",dogName,foodName);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 以後調用方法,大都以這種形式調用
// 調用方法的時候,我們應該具備這樣的思路,養成書寫習慣:
// ①首先調用方法得有 執行個體對象,所以要先建立執行個體對象
// ②其次調用方法前要判斷是否能調用,所以要有判斷語句(對象是否能調用方法)
// ③因為判定對象能調用方法的時候這個方法是以SEL的格式去調用的,所以先要將此方法轉化成SEL的形式
// ④然後判斷結束後,返回值是1就調用,返回值是0就輸出無法調用
// ⑤最後調用 無參/有參 方法(本節所講內容)
//*******************************************************
Animal *ani =[[Animal alloc]init];//①
SEL [email protected](run);//③
BOOL isRespond=[ani respondsToSelector:s1];//②
if (isRespond) {//④
[ani performSelector:s1];//⑤ 執行個體對象調用無參方法
}
else
{
NSLog(@"無法調用!");
}
//*******************************************************
Dog *dog=[[Dog alloc]init];
SEL [email protected](eat:);//這裡擷取含多個參數的方法地址的時候,唯寫方法名即可
BOOL isRespond2=[dog respondsToSelector:s2];
if (isRespond2) {
[dog performSelector:s2 withObject:@"coffee"];//執行個體對象調用含有一個參數的方法
}
else
{
NSLog(@"無法調用!");
}
//*******************************************************
Dog *dog2=[[Dog alloc]init];
SEL [email protected](eat:andDogName:);//唯寫方法名
BOOL isRespond3=[dog respondsToSelector:s3];
if (isRespond3) {
[dog performSelector:s3 withObject:@"hotdog" withObject:@"bigmax"];//執行個體對象調用含兩個參數的方法
}
else
{
NSLog(@"無法調用!");
}
//*******************************************************
}
return 0;
}
———————————————————————————————————————————
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Objective-C 【動態類型檢測&回應程式法】