天天看點

Objective-C中的繼承和多态

   面向對象程式設計之是以成為主流的程式設計思想和他的繼承和多态是分不開的,隻要是面向對象語言都支援繼承和多态,當然不同的OOP語言之間都有其特點。OC中和Java類似,不支援多重繼承,但OOP語言C++就支援多繼承,為什麼OC不支援多繼承稍後将會提到。

   說到繼承呢,想到了一本書上是引用《大話西遊》裡的一句話來描述繼承的。“人是人他媽生的,妖是妖他媽生的!”,想必裡面的唐三藏也學過OOP程式設計,也許他們師徒四人去西天取什麼算法導論呢,漫談OOP程式設計啦,資料結構啦等這類的書去啦。人和妖都屬于動物類,但各自有各自的特點,各自有各自的不同,動物就是父類,而人和妖就是子類。繼承的目的是為了減少代碼的備援,還是DRY原則(don`t repeat yourself)。

        在Objective-C中super是指向直接父類的指針,而self是指向本身的指針,self就相當于java中的this指針。在OC中寫類時可以在@implementation中定義哪些在@interface中無相應聲明的方法,但這個方法是私有的,僅在類的實作中使用。

        在Objectiv-C中幾乎所有的類都是繼承自NSObject類,NSObject類中存在大量功能強大的方法。下面對NSObject類中的各種方法進行試驗和介紹:

        1. +(void) load;  類加載到運作環境時調用該方法

                測試:在子類中重寫load方法來進行測試, 當重寫完load方法,在mian方法中不需要任何執行個體化任何對象

                            當類被加載時load就會别調用.load是類方法,可以直接被類調用

1

2

3

4

5

//重寫NSObject中的load方法

+(

void

) load

{

NSLog(@

"ObjectTest中的load方法被調用啦!!"

);

}

       運作結果:

2014-07-30 08:58:31.704 HelloOC[550:303] ObjectTest中的load方法被調用啦!!

        2. +(void) initialize;  在類第一次使用該類時調用該方法,第二次就不調用了

                測試:重寫initalize方法

//重寫initialize方法,會在類第一次使用時調用

+(

void

) initialize

{

NSLog(@

"initialize方法被調用了(類第一次被執行個體化)!"

);

}

            運作結果:

2014-07-30 09:27:53.767 HelloOC[624:303] load方法被調用啦!!

2014-07-30 09:27:53.769 HelloOC[624:303] initialize方法被調用了(類第一次被執行個體化)!

    3. +(id) alloc:  傳回一個已經配置設定好的記憶體對象;  -(id) init: 對已經配置設定了記憶體的執行個體進行初始化; new同時調用了alloc 和 init

        demo:   Object  *object = [[Object alloc] init];

        可以在子類中把alloc進行重寫,然後觀察運作情況

6

//重寫alloc方法

+(id) alloc

{

NSLog(@

"alloc函數被調用啦"

);

return

[super alloc];

}

7

//重寫init

-(id) init

{

NSLog(@

"init被調用了"

);

self = [super init];

return

self;

}

        測試方法一個用alloc和init執行個體化類,一個用new執行個體化類:

//第一次使用ObjectTest類

ObjectTest *o1 = [[ObjectTest alloc] init];

//第一次使用ObjectTest類

ObjectTest *o2 = [ObjectTest 

new

];

                運作結果:

2014-07-30 09:59:58.991 HelloOC[689:303] load方法被調用啦!!

2014-07-30 09:59:58.993 HelloOC[689:303] initialize方法被調用了(類第一次被執行個體化)!

2014-07-30 09:59:58.993 HelloOC[689:303] alloc函數被調用啦

2014-07-30 09:59:58.993 HelloOC[689:303] init被調用了

2014-07-30 09:59:58.994 HelloOC[689:303] alloc函數被調用啦

2014-07-30 09:59:58.994 HelloOC[689:303] init被調用了

     4.-(void)dealloc 釋放對象自身所占有的記憶體;

    5. -(Class)class 或者 +(Class)class 傳回目前對象的所屬類;  -(Class)superclass 或者 +(Class)superclass傳回目前類的父類

//傳回目前對象所對應的類

NSString *className =(NSString *) [self 

class

];

NSLog(@

"%@類的display方法"

, className);

//傳回目前對象所對應的父類

NSString *superClassName = (NSString *) [self superclass];

NSLog(@

"%@類的父類是%@"

, className, superClassName);

    6、-(BOOL)isKindOfClass : (Class)aClass 判斷某個執行個體是否屬于某個類或者子類的對象

        事例代碼如下:

//isKindOfClass的用法

BOOL

b =  [o2 isKindOfClass:[ObjectTest 

class

]];

if

(b == YES) {

NSLog(@

"o2是ObjectTest類的對象"

);

}

    7.-(BOOL)isMemberOfClass:(Class)aClass;  隻能判斷摸個執行個體是否屬于某個類,不能判斷是否屬于某個父類;

//isMemberOfClass

BOOL

result = [o2 isMemberOfClass:[NSObject 

class

]];

if

(result == NO) {

NSLog(@

"isMemberOfClass不能判斷是否為NSObject子類的對象"

);

}

    8.-(NSString *) description; 傳回字元串形式對象的描述,友善調試

//description

NSString *descript = [o2 description];

NSLog(@

"%@"

, descript);

        輸出結果: <ObjectTest: 0x100206650>

     9.-(NSUInteger) hash; 傳回對象的哈希值;

//hash的用法

NSUInteger hash = [o2 hash];

NSLog(@

"%p"

, hash);

        輸出結果:2014-07-30 11:40:35.685 HelloOC[1130:303] 0x100107b70

    ​10.-(BOOL) isEqual:(id)object; 比較兩個對象是否相同,預設是使用位址進行比較的,且hash值一定要相同

8

9

10

11

//isEqual的用法

NSString *str1 = @

"111"

;

NSString *str2 = str1;

if

([str2 isEqual:str1] == YES)

{

NSLog(@

"str2 == str1"

);

}

else

{

NSLog(@

"str2 != str1"

);

}

    ​    ​Objective-C中的繼承

         繼承是is-a的關系,比如貓咪是一個動物,那麼動物是父類,而貓咪是動物的子類。子類具有父類的屬性和 行為,以及自身的屬性和行為,也就是說“父類更一般,子類更具體”。用一個富二代的類來說明一下類的繼承。

 1.先定義一個富人的類

        代碼說明:

                1.聲明通路權限為@protected的三個屬性,分别為三個屬性用@property加上getter和setter方法

                2.并為該類建立便利初始化方法和便利構造器

                3.為富人類定義一個刷卡方法

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

//

//  Richer.h

//  HelloOC

//

//  Created by ludashi on 14-7-29.

//  Copyright (c) 2014年 ludashi. All rights reserved.

//

#import <Foundation/Foundation.h>

@interface Richer : NSObject

{

@

protected

NSString *name;

int

age;

NSString *gender;

}

//定義富人的姓名,年齡,性别,并為其提供getter和setter方法

@property (copy, nonatomic) NSString *name;

@property (assign, nonatomic) 

int

age;

@property (copy, nonatomic) NSString *gender;

//定義便利初始化方法

-(id) initWithName : (NSString *)vName

AndAge : (

int

)vAge

AndGender : (NSString *)vGender;

//定義便利構造器

+(id) richerWithName : (NSString *)vName

AndAge : (

int

)vAge

AndGender : (NSString *)vGender;

//定義刷卡方法

-(

void

) poss;

@end

    2.為富人類編寫實作代碼

            代碼說明:

                1.用@synthesize實作getter和setter方法

                2.實作便利初始化方法,用[ super init ]初始化富人類的直接父類,也就是NSObject

                3.使用便利構造器傳回執行個體化并初始化後的對象

#import "Richer.h"

@implementation Richer

//實作getter和setter方法

@synthesize name, age, gender;

//實作便利初始化函數

-(id) initWithName : (NSString *)vName

AndAge : (

int

)vAge

AndGender : (NSString *)vGender

{

if

(self = [super init])

{

self->name = vName;

self->age = vAge;

self->gender = vGender;

}

return

self;

}

//實作便利構造器

+(id) richerWithName:(NSString *)vName

AndAge:(

int

)vAge

AndGender:(NSString *)vGender

{

Richer *richer = [[Richer alloc] initWithName:vName

AndAge:vAge

AndGender:vGender];

return

richer;

}

//實作刷卡方法

-(

void

) poss

{

NSLog(@

"%@有錢你就刷吧"

, name);

}@end

    3.編寫富二代的類,富二代和富人有許多相似的屬性和方法是以富二代繼承于富人類,并添加相應的屬性和方法,把需要重寫的方法進行重寫。

                1.為富二代類添加新的愛好屬性

                2.為富二代添加新的方法

#import "Richer.h"

@interface Richer2nd : Richer

//Richer2nd繼承啦Richer所有的方法

//為富二代添加新的屬性

@property (copy, nonatomic) NSString *hobby;

//便利初始化函數

-(id) initWithName : (NSString *) vName

AndAge : (

int

)vAge

AndGender : (NSString *) vGender

AndHobby : (NSString *)vHobby;

//為Richer2nd編寫便利構造器

+(id)richer2ndWithName : (NSString *) vName

AndAge : (

int

)vAge

AndGender : (NSString *) vGender

AndHobby : (NSString *)vHobby;

//添加hobby方法

-(

void

) myHobby;

@end

    4.各種方法的實作

            代碼說明:

                    1.在編寫便利初始化方法時利用super來調用父類的便利初始化方法來把繼承到的父類的方法進行初始化

                    2.用self給新添加的屬性進行初始化

39

40

41

42

43

44

#import "Richer2nd.h"

@implementation Richer2nd

//實作屬性的getter和setter方法

@synthesize hobby;

//編寫便利初始化函數,複用父類的便利初始化方法

-(id)initWithName:(NSString *)vName

AndAge:(

int

)vAge

AndGender:(NSString *)vGender

AndHobby:(NSString *)vHobby

{

if

(self = [super initWithName:vName AndAge:vAge AndGender:vGender]) {

self->hobby = vHobby;

}

return

self;

}

//編寫便利構造函數

+(id)richer2ndWithName:(NSString *)vName

AndAge:(

int

)vAge

AndGender:(NSString *)vGender

AndHobby:(NSString *)vHobby

{

Richer2nd *richer = [[Richer2nd alloc] initWithName:vName AndAge:vAge AndGender:vGender AndHobby:vHobby];

return

richer;

}

//重寫刷卡方法

-(

void

)poss

{

[super poss];

NSLog(@

"我是富二代,我爸有錢,我就刷!"

);

}

//添加新的方法

-(

void

) myHobby

{

NSLog(@

"我是富二代%@,我超喜歡%@"

, name, hobby);

}

@end

    5.以下是上面代碼的運作結果

2014-07-30 08:38:12.956 HelloOC[483:303] Bill有錢你就刷吧

2014-07-30 08:38:12.957 HelloOC[483:303] BILL`s son有錢你就刷吧

2014-07-30 08:38:12.958 HelloOC[483:303] 我是富二代,我爸有錢,我就刷!

2014-07-30 08:38:12.958 HelloOC[483:303] 我是富二代BILL`s son,我超喜歡飙車

​Objective-C中的多态

    ​    ​多态簡單的說就是對于不同對象響應同一個方法時做出的不同反應。在 OC中動态類型id是實作多态的一種方式,id是一個獨特的資料類型,可以轉換為任何資料類型,上面的富人和富二代可以這樣定義

id richer = nil;

//測試富人類

richer = [Richer richerWithName:@

"Bill"

AndAge:40 AndGender:@

"Man"

];

[richer poss];

//測試富二代的類

richer = [Richer2nd richer2ndWithName:@

"BILL`s son"

AndAge:16 AndGender:@

"男"

AndHobby:@

"飙車"

];

[richer poss];

[richer myHobby];

    ​上面程式的輸出結果和繼承部分的結果是一緻的;

    ​多态的另一個例子: Animal是父類,子類有Cat 和 Dog,子分别重寫了父類中的eat方法;執行個體化對象的時候可以用下面的方法:

Animal *animal = nil;

 //執行個體化貓的對象

animal = [Cat 

new

];

[animal eat];

 //執行個體化狗的對象

animal = [Dog 

new

];

[animal eat];

面向對象程式設計中的OCP原則和LSP原則

    ​OCP : Open Closed Principle原則, 對擴充開放,對修改關閉

    ​  LSP :裡氏代換原則,任何基類可以出現的地方,子類一定可以出現。

作者:青玉伏案

出處:http://www.cnblogs.com/ludashi/

本文版權歸作者和共部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

如果文中有什麼錯誤,歡迎指出。以免更多的人被誤導。

收履歷:某網際網路公司,招聘iOS/Android靠譜工程師,入職後,可内部聯系樓主,有小禮品贈送,有意者可郵箱投遞履歷:[email protected]