【GeekBand】objective-c basic1

  • 類與對象
  • 數(shù)據(jù)成員
  • 函數(shù)成員

TODO:

  • 初始化器和析構(gòu)器
  • 繼承
  • 多態(tài)

類與對象

Objective-C(以下簡稱OC) 是一種面向?qū)ο笳Z言,因此除了基本數(shù)據(jù)類型,它具有類類型。OC 中類的聲明形式類似:

 @interface MyClass: NSObject
 {
  NSString* private;  //實(shí)例變量
  @public NSString* public; //實(shí)例變量
 }
 @property int num;  //屬性
 
 -(void)ObjectMethod: (int)num; //對象方法,又叫實(shí)例方法
 +(void)ClassMethod; //類方法
 
 -(NSString*)private ;
 -(void)setPrivate: (NSString*)str;
 
 @end

OC 用 @interface 聲明類,相當(dāng)于C++語法中的class關(guān)鍵字。@end表示聲明的結(jié)束。OC中的大部分中大部分類都會直接或者間接繼承自NSObject,這是因?yàn)?code>NSObject中定義了一些OC對象通用的方法,比如定義一個類時[[MyClass alloc] init],其中allocinit方法就是在NSObject中定義的,否則我們就要在類定義中自己實(shí)現(xiàn)這兩個方法。

OC中類的聲明放在.h文件,類是現(xiàn)實(shí)存在.m文件。上面聲明的類其實(shí)現(xiàn)類似:

 @implement MyClass
 
 -(void)ObjectMethod: (int)num
 {
  self.num = num;
 }
 
 +(void)ClassMethod 
 {
  NSLog(@"This ClassMethod");
 }
 
 -(NSString*)private {
  return private;
 }
 
 -(void)setPrivate: (NSString*)str {
  private = str
 }

定義一個類對象的語法如下:

 MyClass* myClass = [[MyClass alloc] init]

大概是因?yàn)镺C中的類對象都是分配在堆上的,所以,類對象都聲明為指針的形式。

數(shù)據(jù)成員:屬性和實(shí)例變量

上述類聲明中的有一個數(shù)據(jù)成員,就是

@property in num;

屬性的存取方式

myClass.num = 5;
int someNum = myClass.num;

對于任何屬性,編譯器都會自動生成一個與之關(guān)聯(lián)的實(shí)例變量。比如與num關(guān)聯(lián)的實(shí)例變量是_num。同時還生成一個getter訪問器方法和一個setter訪問器方法。

-(int)num {
 return _num;
}

-(void)setNum: (int)num {
 _num = num;
}

可以發(fā)現(xiàn)這里的_num和它的兩個訪問器和我們在MyClass實(shí)現(xiàn)中定義的NSString* private;形式是類似的。
privatepublic一樣是實(shí)例變量,不同的是,一般的實(shí)例變量(如:private)只能在類的內(nèi)部訪問,都是私有的。為了能在類的外部訪問(如myClass->public = @"hello";),需要在實(shí)例變量聲明語句加上@public前綴(如:public)。
雖然private不能在外部通過->來訪問,但因?yàn)槲覀優(yōu)?code>private編寫了getter訪問器和setter訪問器,在OC中,我們就可以使用myClass.private = @"world"這樣的語法來訪問private,其實(shí)編譯器會自動將該語句轉(zhuǎn)化成[myClass setPrivate:@"world"],也就是實(shí)際是調(diào)用setter方法來訪問private實(shí)例變量的。
可想而知,如果沒有屬性,那么對于每個我們希望通過myClass.XXX形式來訪問的實(shí)例變量,我們都需要為其編寫兩個訪問器方法,這實(shí)在是太過繁瑣。有了屬性這個語法糖,就可以讓編譯器自動為我們完成這些工作了。
同樣,有了屬性,我們也不需要再使用@public關(guān)鍵字,通過->指針訪問符來訪問實(shí)例變量了。

需要注意的時,對于在.h.m文件中分別編寫類聲明和類實(shí)現(xiàn)代碼情況,即我們通常所遵循的方式。外部使用時通過#import "xxx.h"只能知道xxx.h文件中的定義,如果我們將某個實(shí)例變量定義在xxx.m的實(shí)現(xiàn)代碼中,那么就是為該實(shí)例變量加上@public前綴,外部對象也不能訪問該實(shí)例變量,因?yàn)樗静恢涝搶?shí)例變量的存在。這點(diǎn)對于方法也是成立的,盡管方法都是public的,但如果方法只在.m文件中定義,沒有在.h文件中聲明,那么對于外部對象該方法就相當(dāng)于是私有的。相當(dāng)于私有并不等于私有,這點(diǎn)在編譯器報錯時可以體現(xiàn)。只定義在.m文件中情況,訪問時編譯器會提示沒有定義該實(shí)例變量或者方法,而如果是聲明在.h文件中非@public實(shí)例變量,訪問時編譯器會提示該實(shí)例變量是受保護(hù)的。

函數(shù)成員:方法

OC中的方法都是public的,沒有 private 和 protected 方法。
OC中類的方法分為實(shí)例方法類方法,聲明形式如下

-(void)ObjectMethod: (int)num; //對象方法,又叫實(shí)例方法
+(void)ClassMethod; //類方法

在語法層面,實(shí)例方法就是通過實(shí)例對象來調(diào)用的方法,如[myClass ObjectMethod:10],定義時在方法名前加-前綴;類方法就是通過類名來調(diào)用的方法,如[MyClass ClassMethod],定義時在方法名前加+前綴。
[[MyClass alloc] init],其中alloc就是類方法,init就是實(shí)例方法。

類方法中是不能訪問本類的實(shí)例成員的。在邏輯上類方法可以在類對象不存在時調(diào)用,此時實(shí)例變量都還不存在,那么通過類方法訪問實(shí)例成員必然出錯。即使類對象存在,假設(shè)有多個類對象,那么類方法是訪問那個類對象的實(shí)例成員也是無法確定。在實(shí)現(xiàn)上,編譯器會為實(shí)例方法自動添加指向當(dāng)前對象的self指針參數(shù),通過self就能確定所訪問的對象。而類方法是沒有self參數(shù)的,所以類方法無法確定是哪個類對象。

OC中方法的外部參數(shù)名不同,就是不同的方法。因此可以寫方法名相同,參數(shù)類型和數(shù)量相同,以及返回值相同的,只有外部參數(shù)名不同的多個方法。

-(void)sum: (int)arg1 arg2: (int)arg2;
-(void)sum:(int)arg1 secondArg: (int)arg2;

這樣的兩個方法是可以同時存在的。

初始化器和析構(gòu)器

初始化器

    MyClass* myClass = [[MyClass alloc] init]

OC中創(chuàng)建一個對象需要配合使用allocinit兩個方法。正如方法名的字面意思,alloc方法用于分配對象空間,init方法用于對對象的實(shí)例變量進(jìn)行初始化操作。
alloc方法在NSObject中已經(jīng)定義,這也是我們的類要繼承于NSObject的原因之一。alloc方法會將分配的內(nèi)存空間用0來填充,這樣所有的實(shí)例變量的值就會是0或者nil。
init的方法中,會先調(diào)用父類的init方法,再初始化自己的實(shí)例變量。
init是對象初始化器,在調(diào)用init之前還會調(diào)用一個類初始化器initialize。

@implementation MyClass 
...
-(id)init {
    self = [super init];
    NSLog(@"this init");
    return self;
}

+(void)initialize {
    if self == [MyClass class] {
        NSLog(@"this is initialize");
    }
}
...
@end

在類定義中實(shí)現(xiàn)這兩個初始化器,然后調(diào)用MyClass* myClass = [[MyClass alloc] init]
會輸出如下結(jié)果:

結(jié)果

類型初始化器initialize只能有一個,而對象初始化器init可以有多個。

- (id)init;
- (id)initWithName: (NSString*)name;
- (id)initWithLocation: (NSPoint*)location;

在初始化器中,要使用實(shí)例變量,不要使用屬性。

析構(gòu)器 dealloc

在析構(gòu)器中,主要做三件事

  1. ARC對對象屬性的引用計數(shù)器減1,這個造作是自動完成。
  2. 手動釋放我們自己分配的動態(tài)內(nèi)存
  3. 關(guān)閉非內(nèi)存資源,比如文件句柄,socket連接等
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容