Objective-C(02)|類的定義和對象初始化(初階)
書接前文,奇怪的語法體驗繼續!
對象的初始化
和Java的new運算符不同,OC的對象初始化使用初始化方法(initializer),個人覺得比new運算符更酷,這方法名和C語言中動態分配內存空間的malloc很像。
實例的生成:
[ClassName alloc]
Cocoa中某個類的對象的生成:
[[ClassName alloc] init ]
通常嵌套調用alloc和init來生成對象。
初始化方法并不具備該對象的重置功能,需單獨使用reset方法。
類的定義
和Java類似,OC中類的定義和實現可以分離,即類本身和對外的接口(我是這么理解的)。
接口聲明
類的接口部分定義類的實例變量和方法,通常聲明為頭文件。給需要調用這個類的模塊引用。
接口的聲明eg:
@interface ClassName : SuperClassName
{
id value1;
int value2;
double value3;
BOOL value4;
}
- (id)method1: (id)obj;
- (void)dealloc;
- (double)method2: (int)someone;
@end
所有的OC編譯指令(compiler directive)都以“@”開頭,和C語言的字符串區分。類的接口聲明使用@interface和@end包起來,@end后不接分號。
接口聲明,必須寫父類。
類的實現
類的實現部分不用再次聲明父類。
實現部分則是上述接口聲明中所有方法的實現。方法內部可以自由使用實例變量。方法內部定義的局部變量和C語言的局部變量同理。若局部變量和實例變量重名,則實例變量將被覆蓋,方法的參數名同理。方法中的“self”即實例本身,相當于Java的“this”。
OC的源代碼文件以“.m”結尾,m意味模塊,使用clang編譯器即可識別為Objective-C源程序文件。
接口的聲明必須放在實現和main函數之前。
一個例子
書中的例子,代碼:
接口定義為頭文件:Volume.h
#import <Foundation/NSObject.h>
@interface Volume : NSObject
{
int val;
int min, max, step;
}
- (id)initWithMin:(int)a max:(int)b step:(int)s;
- (int)value;
- (id)up;
- (id)down;
@end
類的實現:Volume.m
#import "Volume.h"
@implementation Volume
- (id)initWithMin:(int)a max:(int)b step:(int)s
{
self = [super init];
if (self != nil)
{
val = min = a;
max = b;
step = s;
}
return self;
}
- (int)value
{
return val;
}
-(id)up
{
if ((val += step) > max)
val = max;
return self;
}
-(id)down
{
if ((val -= step) < min)
val = min;
return self;
}
@end
可執行程序入口,main函數:VolumeTest.m
#import <stdio.h>
#import "Volume.h"
int main(void)
{
id v, w;
v = [[Volume alloc] initWithMin: 0 max:10 step:2];
w = [[Volume alloc] initWithMin: 0 max:9 step:3];
[v up];
printf("%d %d\n", [v value], [w value]);
[v up];
[w up];
printf("%d %d\n", [v value], [w value]);
[v down];
[w down];
printf("%d %d\n", [v value], [w value]);
return 0;
}
類的實現.m文件,必須使用import導入接口的頭文件,而頭文件中若不指定具體的繼承類,則強制繼承NSObject類。
體會和理解
奇怪的語法,從直接感受來說,接口的定義,或者說方法的定義,在參數的表示部分很像消息表達式,例如本例中的
- (id)initWithMin:(int)a max:(int)b step:(int)s
如果用C或者Java的眼光來看,參數列表不用小括號包裹就已經很不習慣了,但是這里的參數列表貌似又顯得更有“人情味”;同消息表達式中:
通常把消息的關鍵字按照英文的語序來組織。
那么此處,參數a就是給初始化最小值用,b給實例參數max用,s給實例參數step用,這樣的話,尤其是第一個參數就有了用處的表達,表達內容就是方法名。
這樣的定義方式,,習慣和熟練運用需要時間。
指定初始化方法(designed initializer)
指能確保所有實例變量都能夠完成初始化的方法,這種方法是初始化的核心,類的非初始化方法會調用指定初始化方法完成初始化。
一般地,接收參數最多的初始化方法就是指定初始化方法,一個類可以有不止一個的指定初始化方法。
子類的指定初始化方法通常是給super發送消息來調用超類的指定初始化方法,且必須調用超類的指定初始化方法。
繼承關系中,各個類的指定初始化方法會從下到上連鎖調用,直到最上層的NSObject的init方法為止,故需注意不要造成遞歸無限循環。
還有一些通過封裝來調用指定初始化方法的非指定初始化方法。


浙公網安備 33010602011771號