簡單類型就不說了,基本上每個語言都差不多。本次我們僅讨論非簡單資料類型。
類的繼承
頭檔案
#import <Foundation/Foundation.h>
// MyDummy類從NSObject繼承而來
@interface MyDummy : NSObject
/*
* '-'辨別是執行個體方法而不是靜态方法;
* 傳回值用'()'括号括起來,後面跟上方法名;
* 冒号後跟上第一個參數類型(繼續使用括号括起來)和參數
* 空格後跟第二個參數+冒号+類型+參數名
* 最後用分号結束
*/
- (void)foo:(NSString *)username password:(NSString *)passwd;
@end
實作檔案
#import "MyDummy.h"
@implementation MyDummy
/*
* 根據聲明生成
*/
-(void)foo:(NSString *)username password:(NSString *)passwd {
NSLog(@"Your name is %@, your password is %@", username, passwd);
}
@end
測試檔案
#import <Foundation/Foundation.h>
#import "MyDummy.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSString *username = [[NSString alloc] initWithFormat:@"Sam"];
NSString *password = [[NSString alloc] initWithFormat:@"sssssssssss"];
MyDummy *dummy = [[MyDummy alloc] init];
[dummy foo:username password:password];
}
return 0;
}
Category
category和繼承有部分類似,不過相對來說比繼承關系要簡單,我們看一下:
頭檔案
#import "MyDummy.h"
// 注意聲明方式與繼承不同
@interface MyDummy (MyDummy_SayHello)
// 方法的聲明方式完全相同
-(void) sayHello:(NSString *)username password:(NSString *)password;
@end
實作檔案
#import "MyDummy+MyDummy_SayHello.h"
@implementation MyDummy (MyDummy_SayHello)
-(void) sayHello:(NSString *)username password:(NSString *)password {
// 直接調用現有Dummy方法
return [self foo:username password:password];
}
@end
測試檔案
#import <Foundation/Foundation.h>
#import "MyDummy.h"
#import "MyDummy+MyDummy_SayHello.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSString *username = [[NSString alloc] initWithFormat:@"Sam"];
NSString *password = [[NSString alloc] initWithFormat:@"sssssssssss"];
// 聲明一個Dummy類的對象
MyDummy *dummy = [[MyDummy alloc] init];
// 對象的方法被擴充了
[dummy sayHello:username password:password];
}
return 0;
}
Protocol--協定
Protocol在java中對應的是接口。我們在ObjectC中這樣使用:
定義protocol
#import <Foundation/Foundation.h>
@protocol IComparable <NSObject>
-(int) compare:(NSObject *)other;
@end
實作類的頭檔案
#import <Foundation/Foundation.h>
#import "IComparable.h"
@interface MyNumber : NSObject <IComparable>
@property int num;
-(int) compare:(NSObject *)other;
@end
實作類的實作檔案
#import "MyNumber.h"
#import "IComparable.h"
@implementation MyNumber
@synthesize num;
-(int) compare:(NSObject *)other {
MyNumber *number = (MyNumber *) other;
return [self num] - [number num];
}
@end
測試類
#import <Foundation/Foundation.h>
#import "MyDummy.h"
#import "MyDummy+MyDummy_SayHello.h"
#import "MyNumber.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
MyNumber *num1 = [[MyNumber alloc] init];
MyNumber *num2 = [[MyNumber alloc] init];
[num1 setNum:10];
[num2 setNum:100];
NSLog(@"the number is %d", [num1 compare: num2]);
}
return 0;
}
id(動态類型)
ID類型很常見,例如alloc方法,init方法。ID類型很像以前Object Pascal中的variable類型,可以代表任意一種類型;或者你可以将他看成Java中的Object類型。但是一個很明顯的差别在于:Java是強類型語言,是以所有的類型轉換、方法調用都會檢查類型;但ObjectC中,隻要你将一個變量定義為id,那麼編譯器不會再做類型檢查工作,甚至連warning都不抛出。
我們看看代碼:
父類
#import <Foundation/Foundation.h>
@interface ParentClass : NSObject
@end
#import "ParentClass.h"
@implementation ParentClass
@end
第一個子類
#import "ParentClass.h"
@interface Child1 : ParentClass
-(void) foo1;
@end
#import "Child1.h"
@implementation Child1
-(void) foo1 {
NSLog(@"foo1 invoked.");
}
@end
第二個子類
#import "ParentClass.h"
@interface Child2 : ParentClass
-(void) foo2;
@end
#import "Child2.h"
@implementation Child2
-(void) foo2{
NSLog(@"foo2 invoked.");
}
@end
測試代碼
#import <Foundation/Foundation.h>
#import "ParentClass.h"
#import "Child1.h"
#import "Child2.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSLog(@"child1");
Child1 *child1 = [[Child1 alloc] init];
[child1 foo1];
// 下面這一句無法編譯
// [child1 foo2];
NSLog(@"child2");
id child2 = [[Child2 alloc] init];
// 下面這一句會爆出異常
// [child2 foo1];
[child2 foo2];
NSLog(@"child3");
id child3 = [[Child2 alloc] init];
// 下面這一段先判斷類型,之後調用,安全
if ([child3 isKindOfClass:[Child1 class]]) {
// 下面這句不會調用
[child3 foo1];
}
// 下面這一段先判斷是否包含指定方法,之後調用,同樣安全
if ([child3 respondsToSelector:@selector(foo2)]) {
// 下面這句會調用
[child3 foo2];
}
}
return 0;
}