天天看點

016-類與對象-OC筆記

1.【了解】對象在記憶體中的存儲

2.【了解】nil和NULL

3.【了解】#pragma mark分組導航标記

4.【了解】方法與函數

5.【掌握】多檔案開發

6.【掌握】對象和方法

7.【掌握】對象和屬性

類加載:

當程式啟動時,會附加元件目中所有的類和分類,而且加載後會調用每個類和分類的+load方法,而且隻會調用一次。并且類一旦加載到記憶體,就不會被回收,直到程式結束的時候才會被回收。這個過程就叫做類加載。

當第一次使用某個類建立對象的時候,就會調用目前類的+initialize方法,也就是初始化對象,使建立出來的對象可以使用。

對象在記憶體之中是如何存儲的呢?我們這裡的p指針是在函數中聲明的,那麼p就是一個局部指針變量,也就是p變量存儲在棧空間中。比如:

int main(){

    Person *p = [Person new];

    return 0;

}

new做了什麼事情?

1.申請空間:在堆記憶體之中根據類的“模闆”申請一塊合适大小的空間建立對象。類“模闆”中有哪些屬性,就把這些屬性聲明在這塊空間之中。對象中聲明了類定義的所有的屬性和_isa指針和引用計數器(_isa指針指向代碼段中的類)。

2.初始化對象:初始化這塊空間之中對象的屬性的值,就是為屬性賦預設值。

3.傳回對象位址:傳回這塊空間的記憶體位址。

通過指針通路對象的屬性和方法?

1.通路屬性:通過指針可以找到指針指向的堆空間中的對象,找到對象後就可以直接通路對象的屬性。

2.調用方法:根據指針找到堆空間中的對象,在根據對象中的_isa指針找到代碼段中的類中的方法。

NULL是C中指針變量的值,代表這個指針不指向任何變量,這個時候NULL等價于0。

int *p = NULL;//等價于int *p = 0;

nil是OC中指針變量的值,代表這個指針不指向任何對象,這個時候nil等價于0。

Person *p = nil;//等價于Person *p = 0;

注意:

1.其實NULL和nil都是一個宏,并且宏值都是0。隻不過NULL是在C語言中聲明的宏,nil是在OC中聲明的宏。是以在使用的時候應該區分開來使用。在OC中盡量使用nil,C中隻能使用NULL。

2.如果一個類指針沒有指向任何對象,通過這個指針去通路對象的屬性的時候會報錯。通過這個指針去調用方法的時候不會報錯,但是不會有任何回應。

1.#pragma

mark 分組名

在導航欄顯示分組名

2.#pragma

mark -

在導航欄顯示一條水準線

3.#pragma

mark - 分組名

在導航欄顯示分組名,分組名上面加一條水準線

函數指的是C語言中的函數,方法指的是定義在OC類中的方法。

不同點:

1.函數除了不能定義在@interface之中,可以定義在源檔案中其他的任意地方(建議不要寫在類中)。方法的聲明隻能寫在@interface中,方法的實作隻能寫在@implementation中(文法強制要求)。

2.函數可以直接調用(函數是孤立的)。而方法隻能建立對象,通過對象名來調用(方法歸屬于類或者對象)。

相同點:

1.無論是函數還是方法,他們都是封裝了一個代碼塊,代表一個單獨的功能。

如果我們開發一個程式,不可能将所有的類都寫在同一個源檔案,後期維護和團隊開發都非常不友善。是以我們需要分子產品開發,并且每個子產品包含兩個檔案,分别是類的聲明檔案和實作檔案。類的聲明寫在.h檔案,類的實作寫在.m檔案(類的實作裡也要引入類的聲明檔案),使用這個類之前用#import引入.h檔案就行了。

建立檔案的時候選擇Cocoa

Class,檔案名使用類名,就會同時建立類的聲明檔案和類的實作檔案。然後我們在.h檔案中寫類的聲明,在.m檔案中寫類的實作。例如:

Person.h檔案

#import

@interface Person : NSObject

{

@public

    NSString *_name;

- (void)sayHi;

@end

Person.m檔案

#import "Person.h"

@implementation Person

- (void)sayHi{

    NSLog(@"你好%@",_name);

main.m檔案

int main(int argc, const char * argv[]) {

    @autoreleasepool {

  Person *p = [Person new];

  p -> _name = @"jack";

  [p sayHi];

    }

對象可以作為方法的參數,因為類的本質就是一個資料類型。并且傳遞的時候是位址傳遞,相當于在方法中操作的參數和實參是同一個對象。

Gender.h檔案

//單獨在一個頭檔案中定義一個性别枚舉

typedef enum{GenderMale,GenderFemale}Gender;

#import "Gender.h"

    Gender _gender;

    int _age;

//人的打招呼方法聲明

//人的打招呼方法實作

NSLog(@"我是%@,性别%@,年齡%i",_name,_gender == 0 ? @"男" : @"女",_age);

God.h檔案

@interface God : NSObject

//上帝的打招呼方法聲明

//上帝殺死一個人的方法聲明

- (void)killWithPerson:(Person *)person;

God.m檔案

#import "God.h"

@implementation God

//上帝的打招呼方法實作

NSLog(@"我是%@,性别%@",_name,_gender == 0 ? @"男" : @"女");

//上帝殺死一個人的方法實作

- (void)killWithPerson:(Person *)person{

    person -> _age = 0;

    NSLog(@"%@已經被%@殺死",person

-> _name,self -> _name);

  //執行個體化一個人對象

  //給這個對象的成員變量指派

  p -> _name = @"小明";

  p -> _gender = GenderMale;

  p -> _age = 21;

  //調用這個對象的打招呼方法

  [p sayHi];//輸出 我是小明,性别男,年齡21

  //執行個體化一個上帝對象

  God *g = [God new];

  g -> _name = @"上帝";

  //調用這個對象的殺死人方法

  [g killWithPerson:p];//輸出 小明已經被上帝殺死

  NSLog(@"小明的壽命等于:%i",p->_age);//輸出

小明的壽命等于:0

//上帝造人的方法

- (Person *)makePersonWithName:(NSString *)name;

- (Person *)makePersonWithName:(NSString *)name{

    p -> _name = name;

    NSLog(@"上帝制造了一個叫%@的人",p ->

_name);

    return p;

  //上帝制造了一個人

  Person *p = [g makePersonWithName:@"小明"];//輸出

上帝制造了一個叫小明的人

  //給制造出來的對象的成員變量指派

  p -> _age = 19;

  //調用這個對象的方法

  [p sayHi];//輸出 我是小明,性别男,年齡19

對象可以作為類的執行個體變量,比如我們有一個人類和一個狗類,每一個人擁有一隻狗,那狗也是人的屬性了。比如:

Dog.h檔案

@interface Dog : NSObject

@property (nonatomic,copy) NSString *name;//狗名

- (void)shout;//狗叫的方法聲明

Dog.m檔案

#import "Dog.h"

@implementation Dog

//狗叫的方法實作

- (void)shout{

    NSLog(@"叫%@的狗叫了",_name);

@property (nonatomic,retain) Dog *dog;//人的狗

  Person *person = [[Person alloc] init];

  //給人對象的dog成員指派一個狗對象

  person.dog = [[Dog alloc] init];

  person.dog.name = @"小白";

  //調用狗對象叫的方法

  [person.dog shout];