天天看點

【Objective-C學習筆記】OC三大特性:封裝、繼承、多态

第一部分 封裝 一、封裝的作用 1、過濾不合理的值

2、屏蔽内部的指派過程

3、讓外界不必關注内部的細節

二、set方法和get方法 1、使用場合 被@public修飾的成員變量可以在任何位置随意的指派,這樣很不安全,我們應該使用set方法和get方法來管理成員變量的通路。

#import <Foundation/Foundation.h>

@interface Student : NSObject
{
    int _age;   
}

- (void)setAge:(int)age;    //set方法

- (int)age;    //get方法

@end

@implementation Student
// set方法的實作
- (void)setAge:(int)age
{
    // 對傳進來的參數進行過濾
    if (age <= 0)
    {
        age = 1;
    }
    
    _age = age;
}
// get方法的實作
- (int)age
{
    return _age;
}

@end

int main()
{
    Student *stu = [Student new];
    
    [stu setAge:-10];
    
    NSLog(@"學生的年齡是%d歲", [stu age]);
  
    return 0;
}
// 學生的年齡是1歲,因為在set方法中,會對傳入的參數過濾,-10歲這樣的年齡不合理。
           

2、成員變量的命名規範 (1)一定要以下劃線 _ 開頭

(2)作用:

1> 讓成員變量和get方法的名稱區分開

2> 可以跟局部變量區分開,一看到下劃線開頭的變量,一般都是成員變量

3、set方法 (1)作用:提供一個方法給外界設定成員屬性值,可以在方法裡面對參數進行相應過濾

(2)命名規範:

1> 方法名必須以set開頭

2> set後面跟上成員變量的名稱,成員變量的首字母必須大寫

3> 傳回值一定是void

4> 一定要接收一個參數,而且參數類型跟成員變量類型一緻

5> 形參的名稱不能跟成員變量名一樣

4、get方法 (1)作用:傳回對象内部的成員變量

(2)命名規範:

1> 肯定有傳回值,傳回值類型肯定與成員變量類型一緻

2> 方法名跟成員變量名一樣

3> 不需要接收任何參數

三、類方法

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    int age;
}

// 類方法是以+開頭
- (void)test;
+ (void)test;
@end

@implementation Person

- (void)test
{
    NSLog(@"111");
}

+ (void)test
{
    NSLog(@"333");    //不能通路成員變量
}

@end

int main()
{
    Person *p = [Person new];
    [p test];    //對象方法調用

    [Person test];    //類方法調用
    
    return 0;
}
           

1、類方法的命名規範 (1)加号 + 開頭

(2)方法隻能由類(名)調用

(3)類方法中不能通路執行個體變量(成員變量)

2、與對象方法的差別以及優點 (1)對象方法

1> 減号 - 開頭

2> 隻能由對象來調用

3> 對象方法中能通路目前對象的執行個體變量(成員變量)

(2)優點 1> 不依賴于對象,執行效率高

2> 能用類方法盡量用類方法

3> 類方法和對象方法的名字可以相同 3、使用場合 當方法内部不需要使用到成員變量時,就可以改為類方法

四、self關鍵字 1、self是指針,指向目前方法的調用者 2、self的用途

(1)誰調用了目前方法,self就代表誰

1> self出現在對象方法中,self就代表對象

2> self出現在類方法中,self就代表類

(2)在對象方法中利用"self->成員變量名"通路目前對象内部的成員變量

(3)[self 方法名]可以調用其他對象方法或者類方法;

1> 如果在對象方法中,可以調用類方法

2> 如果在類方法中,一定不能調用對象方法 第二部分 繼承 一、繼承的格式以及優點

#import <Foundation/Foundation.h>

/******** Animal的聲明 ********/
@interface Animal : NSObject
{
    int _age;
}

- (void)setAge:(int)age;
- (int)age;
@end

/******** Animal的實作 ********/
@implementation Animal
- (void)setAge:(int)age
{
    _age = age;
}
- (int)age
{
    return _age;
}
@end

/******** Dog ********/
@interface Dog : Animal    //Dog是子類,Animal是父類,子類繼承父類
@end

@implementation Dog
@end

int main()
{
    Dog *d = [Dog new];
    
    [d setAge:10];
    
    NSLog(@"age=%d", [d age]);
    
    return 0;
}
           

1、繼承的基本使用 (1)子類方法和屬性的通路過程:如果子類沒有,就去通路父類的 (2)雖然被繼承了,但是父類中的執行個體變量和方法還是能繼續使用 2、繼承的好處:

(1)抽取重複代碼

(2)建立了類之間的關系,Dog是Animal的子類,Animal是Dog的父類。

(3)子類可以使用父類中的所有成員變量和方法,Dog : Animal,繼承了Animal,相當于擁有了Animal裡面的所有成員變量和方法。

3、繼承的細節: (1)基本上所有類的根類是NSObject

(2)不允許子類和父類擁有相同名稱的成員變量 4、重寫: (1)子類重新實作父類中的某個方法,覆寫父類以前的做法 (2)注意點 1> 父類必須聲明在子類的前面,不用管父類的實作。

2> 調用某個方法時,優先去目前類中找,如果找不到,就去父類中找。

(3)super關鍵字 1> 使用場合:在子類方法中,想直接調用父類方法 2> 注意:super處在對象方法中,那麼就會調用父類的對象方法;super處在類方法中,那麼就會調用父類的類方法

5、繼承的使用場合 (1)當B類是A類的時候,就讓B類繼承A類

@interface Person : NSObject    //A類:人
@end

@interface Student : Person    //B類:學生
@end
           

(2)當B類擁有A類的時候,就寫成組合

@interface Car : : NSObject    //A類:車
{
    int _speed;    //速度
    int _wheels;    //輪子
}
@end

@interface Person : NSObject    //B類:人
{
    Car *_car;    // 人擁有車
    int _age;    //年齡
}
@end
           

第三部分 多态 一、多态的基本使用

#import <Foundation/Foundation.h>
@interface Animal : NSObject
- (void)eat;
@end

@implementation Animal
- (void)eat
{
    NSLog(@"Animal-eat!");
}
@end

@interface Dog : Animal
@end

@implementation Dog
- (void)eat
{
    NSLog(@"Dog-eat!");
}
@end

int main()
{
    Dog *d = [Dog new];
    // 多種形态
    Animal *a = [Dog new];
    [a eat];    // Dog-eat!
    return 0;
}
           

1、子類對象指派給父類指針 2、調用方法時,會檢測對象的真實形象,在運作時根據對象的類型确定動态調用的方法。雖然指針是父類,但是對象實際是子類,那麼會去子類裡面找eat方法

二、多态的好處

void feed (Animal *aa)
{
    [a eat];
}

Animal *a = [Animal new];
feed(a);    //Animal-eat!

Dog *d = [Dog new];
feed(d);    //Dog-eat!
           

1、如果參數中使用的是父類類型,可以傳入父類、子類對象,節省代碼 2、傳入以後,會檢測對象的真實形象,然後執行方法

三、多态的局限性 1、父類類型指針變量不能直接調用子類對象中特有的方法

// 狗類特有的方法
- (void)run
{
    NSLog(@"Dog-run!");
}

Animal *a = [Dog new];
// 編譯器會警告Animal類中沒有run這個方法
// [a run];
           

2、把父類強轉成子類,才可以調用。

// 将a轉為Dog *類型的變量
Dog *dd = (Dog *)a;
    
[dd run];