你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS開發入門 ☞ OC語言·筆記六

iOS開發入門 ☞ OC語言·筆記六

編輯:IOS開發綜合

面向對象的三大特性: 封裝, 繼承, 多態 1. 封裝

1.1 基本概念

將零散的東西組合起來。

  • 廣義上封裝指:將代碼封裝成函數,將實例變量和方法封裝成類,將類封裝成框架....
  • 面向對象中的封裝指:封裝屬性和方法放在一個對象中,只給外界公開訪問的接口,而且把具體實現隱藏起來。

1.2 封裝的好處

提高可讀性,可維護性,可擴展性

1.3 OC中的封裝

OC語言天然就是封裝好的。

定義一個類時,@interface部分就是給外界公開的訪問接口。@implementation部分就是隱藏起來的具體實現。

.h文件中寫的是公開的接口

.m文件中寫的是隱藏的實現

//私有方法,只要不在頭文件的接口部分聲明的方法就是私有方法

2. 繼承

2.1 概念

繼承是一種代碼復用技術(代碼重復使用)。是類與類之間的一種關系(“is a”關系)。

B類繼承了A類。A類叫B類的父類,B類叫A類的子類。

其他語言中還有基類,派生類的概念

2.2 繼承的方式

    單繼承  OC, Java...., Swift    單繼承指一個類只能有一個父類.

    多繼承  C++支持多繼承      多繼承指一個類可以有多個父類.

    OC語言中的類在一顆樹上,只有一個祖宗NSObject; swift不只有一顆樹,是一片森林。

2.3 OC中繼承的語法

@interface 類名 : 父類名

 

@end

2.4 什麼情況下用繼承

理論上:

      如果兩個類之間擁有is a關系,這兩個類應該是繼承關系。

  狗是動物  Dog is a Animal.

        Animal是父類, Dog是子類

      如果兩個類之間擁有has a關系,應該用組合或聚合

  計算中有一個CPU  Computer has a CPU

  組合和聚合是另一種類與類之間的關系

實際開發中使用繼承:

先寫的父類,還是先寫的子類?//都可以

 

2.5 抽象類

C++: 純虛函數,沒有函數體的函數。存在純虛函數的類是抽象類,不可以實例化了對象。

Java: 抽象方法和抽象類, abstract來聲明

OC: OC語言中沒有抽象類和抽象方法的語法。

派生:在子類中添加新的屬性和方法

2.6 重寫:子類對父類的方法不滿意時,可重寫父類中的方法

   隱藏:當子類重寫父類的方法後,子類中將有兩個同名的方法,而從父類中繼承的方法不能在類外被調用

2.6.1 概念

1) override 重寫(覆蓋): 子類不滿意從父類中繼承來的方法,重新將此方法實現了。

要求:方法名和父類一樣,參數類型一樣,返回值一樣。只有方法的實現不一樣。

2) overload 重載: OC中並不存在overload。

overload的概念是在一個范圍內(比如一個類中),出現多個方法名相同的方法,這些方法的參數類型不同,導致可以同時出現,我們說,這些方法之間形成了重載的關系。

OC中不允許同一個范圍存在多個方法名相同的方法。

-(id)initWithName:(NSString *)name andAge:(NSUInteger)age;

-(id)initWithName:(NSString *)name andGender:(BOOL)gender; //OC中方法名不同

OC中只有重寫,沒有重載

方法的重寫:子類對父類繼承的方法不滿意,可以在子類中重寫父類的方法。

如果重寫父類的方法,優先調用子類的方法,如果子類沒有重寫父類的方法,則調用父類的方法。

 

2.6.2 注意

雖然父類中的屬性是公開的,但生成的實例變量卻是私有的,在子類中不能訪問

2.6.3 普通方法的重寫

如同perimeter, area, show

方法名相同,參數類型相同,返回值相同

2.6.4 屬性的重寫

如同TRSqaure中的width,height屬性

2.6.5 特殊方法的繼承和重寫

1) 初始化方法

在OC中初始化方法是會被繼承的。

繼承來的初始化方法有些可以用,有些不能用。

如果在子類中,繼承自父類的初始化方法不能用(不能完成要求的初始化任務),在子類中就需要重寫這個初始化方法。

2) 類方法(工廠方法)

類方法也可以被繼承

工廠方法自然也可以被繼承,但直接繼承的工廠方法名不匹配,實際開發中很少這樣用。子類最好提供自己的工廠方法。

2.7 繼承的缺陷

  1) 提高了程序的復雜度,維護性和擴展性降低。 

  2) 破壞類的封裝性  慎用繼承!

2.8 為什麼使用繼承?

  1) 代碼復用 

    將子類重復的代碼抽象到父類中

  2) 制定規范(規則)

    NSObject  

  3) 為了多態

    沒有繼承,就沒有多態

組合與聚合

  類與類之間的一種關系,比較常見;主要作用:代碼復用!

1.1 什麼是組合

  表示兩個對象之間是整體和部分的強關系,是“contains(包含) a”關系,要求兩個類同生共死。

生命周期完全一致,同生共死。部分的生命周期不能超越整體!

例如:一個窗口內有按鈕、標簽,當窗口關閉時,窗口與按鈕、標簽同時銷毀。

 

1.2 組合的定義:

@interface BRButton : NSObject

@end

@interface BREdit : NSObject

@end

@interface BRWindow : NSObject

/**

 *  組合是兩個類的強關系(要求定義成成員變量)

 *  1.在對象初始化時給實例變量賦值(同生共死)

 *  2.不能在類的外部對實例變量訪問/賦值

 */

{

    BRButton *button;

    BREdit *edit;

}

@end

 

  組合Demo:

    

    

1.3 組合的優缺點:

優點:

1)當前對象只能通過所包含的那個對象去調用其方法,所以所包含的對象的內部細節對當前對象是不可見的。

2)當前對象與包含的對象是一個低耦合關系,如果修改包含對象的類中代碼,不需要修改當前對象類的代碼。

3)當前對象可以在運行時動態的綁定所包含的對象。可以通過set方法給所包含對象賦值。

缺點:

容易產生過多的對象

為了能組合多個對象,必須仔細對接口進行定義。

 

1.4 什麼是聚合

表示兩個對象之間是整體和部分的弱關系,是”has a”關系,不要求兩個類同生共死。

生命周期不一致,一個類無法控制另一個類的生死。部分的生命周期可以超越整體。

例如:電腦和鼠標,電腦被銷毀時,鼠標可以留下在其他電腦上繼續使用。

1.5 聚合的定義

@interface BRMouse : NSObject

@end

@interface BRComputer : NSObject

//聚合是兩個類的弱關系,在類的外部給實例變量賦值(要求定義成屬性)

@property BRMouse *mouse;

@end

 

  聚合Demo:

    

1.6 聚合的優缺點:

優點:

1)被包含的對象通過包含它們的類來訪問

2)很好的封裝

3)被包含的對象內部細節不可見

4)可以在運行時動態定義聚合的方式

缺點:

1)系統可能會包含太多對象

2)當使用不同的對象時,必須小心定義的接口。

組合和聚合的生命周期不一樣,組合是同生共死(關系緊密);聚合沒有特別的關系。

 

1.7  類與類之間常見的三種關系:繼承、組合、聚合

  1) 繼承(繼承的主要目的:代碼復用,制定規范,為了多態)  慎用繼承!(is a關系才用繼承,否則濫用繼承)

  2) 組合和聚合(單純的為了代碼復用)

      組合和聚合的主要目的:是為了代碼的復用。

   

應用場景:(代碼的重復使用。如果想使用別人的代碼,組合、聚合在一起就可以了)

實際開發中,如果為了復用代碼,提倡使用組合或聚合來復用,而不用繼承。即是把一個類作為另一個類的屬性。(整體與部分)

 

一個類想使用另一個類的方法?怎麼實現...

1.繼承:我繼承你,我就可以直接調你的方法(提高程序的復雜度…不建議用!)

2.組合/聚合:把你變成我的一部分(即你是我的屬性),我可以通過訪問你去調用你的方法![我.你 你的方法];

 

組合:關系很緊密,同生共死。(cpu焊在主板上,主板壞了cpu也就壞了;綁在一起同生共死!)

聚合:關系很疏遠,不同生共死。(計算機是計算機,cpu是cpu;這個cpu可以用給這個計算機,也可以用給那個計算機,cpu可以從主板上拔下來給另一個計算機用)

3. 多態(Polymorphism)

3.1 什麼是多態

多種形態,引用的多種形態。對於一個引用變量,可以指向任何類的對象 (一個對外接口,多個內在實現)

 

    父類的引用指向本類或任何子類的對象,會調用不同的方法(表現出多種形態,這種表現叫多態)

TRAnimal *animal = [[TRDog alloc]init];//父類的引用指向子類的對象

[animal eat];//狗啃骨頭 (調用子類重寫的方法)

animal = [[TRCat alloc]init];

[animal eat];//貓吃魚

   多態的表現:同一個引用變量s,調用相同的方法(show),顯示不同的結果。

TRShape *s=[[TRRect alloc]init]; //父類的引用指向子類的對象

[s show]; //顯示矩形  調用子類重寫的方法

s=[TRCircle alloc]init];

[s show]; //顯示圓形

 

3.2 編譯期類型和運行期類型

編譯器編譯時,引用的類型叫編譯期類型。

程序運行時,引用指向的類型叫運行期類型。

       

  程序編譯時按編譯期類型找方法編譯,程序運行時按運行期類型找方法調用。

  父類的引用指向子類的對象時,只能調用父類中有的方法。

  因為編譯器在編譯時是按父類來檢查的,雖然運行時調用的是子類的方法,但是編譯時是按父類來檢查的。

3.3 為什麼用多態

為什麼用父類的引用指向子類的對象:

為了寫出更加能用(通用),兼容性更好的代碼。

 

3.4 多態的各種表現【用途】

1)【參數多態】經常在方法的參數表現多態:參數類型使用父類型,可以傳任何子類的對象

NSObject *和id類型做為方法的參數區別在於:

NSObject *類型的引用只能調用NSObject類中有的方法。

id類型的引用可以調用任何存在(不能瞎寫)的方法。

(一般不用NSObject *類型,用id類型替代。id有風險的,編譯器根本不檢查對錯)

/** 方法的參數 表現多態 */

void showAnimal(TRAnimal *animal) {

    [animal eat];

    [animal sleep];

    //[animal watchHome];//父類中沒有這個方法編譯不通過

}

int main() {

    @autoreleasepool {

        TRDog *dog = [[TRDog alloc]init];

        showAnimal(dog);

        showAnimal([TRCat new]);

    }

    return 0;

}

 

  2)【返回值多態】方法的返回值上表現多態

    

3)【數組多態】在數組和集合中表現的多態

//數組 表現多態 [多個對象同時執行eat方法]

TRAnimal *animals[3] = {[TRAnimal new], [TRDog new], [TRCat new]};

for (int i = 0; i < 3; i++) {

[animals[i] eat];

}

  

 多態無處不在!

 

 

多態Demo

  

    

    

 

【iOS開發入門 ☞ OC語言&#183;筆記六】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved