多态---父指针指向子类对象(父类引用指向子类对象)
?
?
我們都知道,面向?qū)ο蟪绦蛟O(shè)計(jì)中的類有三大特性:繼承,封裝,多態(tài),這個也是介紹類的時候,必須提到的話題,那么今天就來看一下OC中類的三大特性:
一、封裝
封裝就是對類中的一些字段,方法進(jìn)行保護(hù),不被外界所訪問到,有一種權(quán)限的控制功能,Java中有四種訪問權(quán)限修飾符:
| 1 | public,default,protected,private |
訪問權(quán)限依次遞減,這樣我們在定義類的時候,哪些字段和方法不想暴露出去,哪些字段和方法可以暴露,可以通過修飾符來完成,這就是封裝,下面來看一個例子吧:
Car.h
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //??Car.h?? //??05_ObjectDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import??? ??? @interface?Car?:?NSObject{?? ????//這個屬性就是對外進(jìn)行保密的相當(dāng)于private,所以我們需要在外部訪問的話,必須定義get/set方法?? ????//默認(rèn)的是private的,但是我們可以使用@public設(shè)置為public屬性的,那么在外部可以直接訪問:person->capcity?=?2.8;?? ????//當(dāng)然我們一般不這么使用,因?yàn)檫@會破壞封裝性,這種用法相當(dāng)于C中的結(jié)構(gòu)體中權(quán)限?? ????//一共四種:@public,@protected,@private,@package,這個和Java中是相同的?? @public?? ????float?_capcity;?//油量屬性?? }?? ??? -?(void)run:(float)t;?? ??? @end |
這里我們可以看到,OC中也是有四種訪問權(quán)限修飾符:
| 1 | @public、@protected、@private、@package |
其中默認(rèn)的修飾符是@private
但是這里要注意的是:OC中的方法是沒有修飾符的概念的,這個和Java有很大的區(qū)別,一般都是公開訪問的,即public的,但是我們怎么做到讓OC中的一個方法不能被外界訪問呢?
OC中是這么做的,如果想讓一個方法不被外界訪問的話,只需要在.m文件中實(shí)現(xiàn)這個方法,不要在頭文件中進(jìn)行定義,說白了就是:該方法有實(shí)現(xiàn),沒定義,這樣外界在導(dǎo)入頭文件的時候,是沒有這個方法的,但是這個方法我們可以在自己的.m文件中進(jìn)行使用。
為什么要介紹這點(diǎn)知識呢?因?yàn)樵诤竺嫖覀儠f到單利模式,到時候就會用到這個知識點(diǎn)了。
二、繼承
繼承是類中的一個重要的特性,他的出現(xiàn)使得我們沒必要別寫重復(fù)的代碼,可重用性很高。當(dāng)然OC中的繼承和Java中是一樣的,沒多大區(qū)別,這里在看一個例子吧:
首先來看一下父類:Car
Car.h
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //?? //??Car.h?? //??06_ExtendDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import??? ??? @interface?Car?:?NSObject{?? ????NSString?*_brand;?? ????NSString?*_color;?? }?? ??? -?(void)setBrand:(NSString?*)brand;?? -?(void)setColor:(NSString?*)color;?? -?(void)brake;?? -?(void)quicken;?? ??? @end |
在Car類中定義了兩個屬性,以及一些方法
Car.m
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | //?? //??Car.m?? //??06_ExtendDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import?"Car.h"?? ??? @implementation?Car?? -?(void)setBrand:(NSString?*)brand{?? ????_brand?=?brand;?? }?? -?(void)setColor:(NSString?*)color{?? ????_color?=?color;?? }?? -?(void)brake{?? ????NSLog(@"剎車");?? }?? -?(void)quicken{?? ????NSLog(@"加速");?? }?? @end |
方法的實(shí)現(xiàn)
在來看一下子類:
Taxi.h
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //?? //??Taxi.h?? //??06_ExtendDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import?"Car.h"?? ??? @interface?Taxi?:?Car{?? ????NSString?*_company;//所屬公司?? }?? ??? //打印發(fā)票?? -?(void)printTick;?? ??? @end |
看到Taxi類繼承了父類Car,這里需要導(dǎo)入父類的頭文件,然后在Taxi類中多了一個屬性和方法
Taxi.m
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //?? //??Taxi.m?? //??06_ExtendDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import?"Taxi.h"?? ??? @implementation?Taxi?? ??? -?(void)printTick{?? ????[super?brake];?? ????[self?brake];?? ????NSLog(@"%@出租車打印了發(fā)票,公司為:%@,顏色為:%@",_brand,_company,_color);?? }?? ??? @end |
?
對方法的實(shí)現(xiàn),這里我們看到實(shí)現(xiàn)文件中是不需要導(dǎo)入父類Car的頭文件的,因?yàn)榭梢哉J(rèn)為,Taxi.h頭文件中已經(jīng)包含了Car的頭文件了。而且,這里可以使用super關(guān)鍵字來調(diào)用父類的方法,同時這里我們也是可以用self關(guān)鍵字來調(diào)用,這里看到其實(shí)這兩種方式調(diào)用的效果是一樣的,當(dāng)我們在子類重新實(shí)現(xiàn)brake方法的時候(Java中的重寫概念),那么這時候super關(guān)鍵字調(diào)用的還是父類的方法,而self調(diào)用的就是重寫之后的brake方法了。同樣,我們也是可以使用父類中的屬性。
再看一下另外一個子類:
Truck.h
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //?? //??Truck.h?? //??06_ExtendDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import?"Car.h"?? //卡車類繼承Car?? @interface?Truck?:?Car{?? ????float?_maxWeight;//最大載貨量?? }?? ??? //覆蓋父類的方法brake?? //優(yōu)先調(diào)用子類的方法?? -?(void)brake;?? ??? -?(void)unload;?? ??? @end |
這里就自己定義了一個brake方法,這時候就會覆蓋父類中的brake方法了。
Truck.m
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | //?? //??Truck.m?? //??06_ExtendDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import?"Truck.h"?? ??? @implementation?Truck?? ??? -?(void)brake{?? ????[super?brake];?? ????NSLog(@"Truck類中的brake方法");?? }?? ??? -?(void)unload{?? ????[super?brake];//調(diào)用父類的方法?? ????[self?brake];//也是可以的?? ????NSLog(@"%@的卡車卸貨了,載貨量:%.2f,汽車的顏色:%@",_brand,_maxWeight,_color);?? }?? ??? @end |
這里就可以看到,我們會在brake方法中調(diào)用一下父類的brake方法,然后在實(shí)現(xiàn)我們自己的邏輯代碼。
好了,繼承就說這么多了,其實(shí)封裝和繼承兩個特性沒什么難度的,很容易理解的,下面在來看一下最后一個特性:多態(tài)
三、多態(tài)
多態(tài)對于面向?qū)ο笏枷雭碚f,個人感覺是真的很重要,他對以后的編寫代碼的優(yōu)雅方式也是起到很重要的作用,其實(shí)現(xiàn)在很多設(shè)計(jì)模式中大部分都是用到了多態(tài)的特性,Java中的多態(tài)特性用起來很是方便的,但是C++中就很難用了,其實(shí)多態(tài)說白了就是:定義類型和實(shí)際類型,一般是基于接口的形式實(shí)現(xiàn)的,不多說了,直接看例子吧:
打印機(jī)的例子
抽象的打印機(jī)類Printer
Printer.h
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //?? //??Printer.h?? //??07_DynamicDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import??? ??? @interface?Printer?:?NSObject?? ??? -?(void)?print;?? ??? @end |
就是一個簡單的方法print
Printer.m
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //?? //??Printer.m?? //??07_DynamicDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import?"Printer.h"?? ??? @implementation?Printer?? ??? -?(void)print{?? ????NSLog(@"打印機(jī)打印紙張");?? }?? ??? @end |
實(shí)現(xiàn)也是很簡單的
下面來看一下具體的子類
ColorPrinter.h
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //?? //??ColorPrinter.h?? //??07_DynamicDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import?"Printer.h"?? ??? //修改父類的打印行為?? @interface?ColorPrinter?:?Printer?? -?(void)print;?? @end |
ColorPrinter.m
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //?? //??ColorPrinter.m?? //??07_DynamicDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import?"ColorPrinter.h"?? ??? @implementation?ColorPrinter?? ??? -?(void)print{?? ????NSLog(@"彩色打印機(jī)");?? }?? ??? @end |
在看一下另外一個子類
BlackPrinter.h
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | BlackPrinter.m //?? //??BlackPrinter.m?? //??07_DynamicDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import?"BlackPrinter.h"?? ??? @implementation?BlackPrinter?? ??? -?(void)print{?? ????NSLog(@"黑白打印機(jī)");?? }?? ??? @end |
這里我們在定義一個Person類,用來操作具體的打印機(jī)
Person.h?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | Person.m //?? //??Person.m?? //??07_DynamicDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import?"Person.h"?? ??? @implementation?Person?? ??? /*? -?(void)?printWithColor:(ColorPrinter?*)colorPrint{? ????[colorPrint?print];? }? ?? -?(void)?printWithBlack:(BlackPrinter?*)blackPrint{? ????[blackPrint?print];? }? ?*/?? ??? -?(void)?doPrint:(Printer?*)printer{?? ????[printer?print];?? }?? ??? @end |
再來看一下測試代碼:
main.m
| 1 2 3 4 5 6 7 8 9 10 11 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 39 40 41 42 43 44 45 | //?? //??main.m?? //??07_DynamicDemo?? //?? //??Created?by?jiangwei?on?14-10-11.?? //??Copyright?(c)?2014年?jiangwei.?All?rights?reserved.?? //?? ??? #import??? ??? #import?"Person.h"?? #import?"BlackPrinter.h"?? #import?"ColorPrinter.h"?? ??? int?main(int?argc,?const?charchar?*?argv[])?{?? ????@autoreleasepool?{?? ??????????? ????????Person?*person?=[[Person?alloc]?init];?? ??????????? ????????ColorPrinter?*colorPrint?=?[[ColorPrinter?alloc]?init];?? ????????BlackPrinter?*blackPrint?=?[[BlackPrinter?alloc]?init];?? ??????????? ????????//多態(tài)的定義?? ????????/*? ????????Printer?*p1?=?[[ColorPrinter?alloc]?init];? ????????Printer?*p2?=?[[BlackPrinter?alloc]?init];? ?????????? ????????[person?doPrint:p1];? ????????[person?doPrint:p2];? ?????????*/?? ??????????? ????????//通過控制臺輸入的命令來控制使用哪個打印機(jī)?? ????????int?cmd;?? ????????do{?? ????????????scanf("%d",&cmd);?? ????????????if(cmd?==?1){?? ????????????????[person?doPrint:colorPrint];?? ????????????}else?if(cmd?==?2){?? ????????????????[person?doPrint:blackPrint];?? ????????????}?? ????????}while?(1);?? ??????????? ????}?? ????return?0;?? } |
下面就來詳細(xì)講解一下多態(tài)的好處
上面的例子是一個彩色打印機(jī)和黑白打印機(jī)這兩種打印機(jī),然后Person類中有一個操作打印的方法,當(dāng)然這個方法是需要打印機(jī)對象的,如果不用多態(tài)機(jī)制實(shí)現(xiàn)的話(Person.h中注釋的代碼部分),就是給兩種打印機(jī)單獨(dú)定義個操作的方法,然后在Person.m(代碼中注釋的部分)中用具體的打印機(jī)對象進(jìn)行操作,在main.m文件中,我們看到,當(dāng)Person需要使用哪個打印機(jī)的時候,就去調(diào)用指定的方法:
| 1 2 | [person?printWithBlack:blackPrint];//調(diào)用黑白打印機(jī)?? [person?printWithColor:colorPrint];//調(diào)用彩色打印機(jī) |
這種設(shè)計(jì)就不好了,為什么呢?假如現(xiàn)在又有一種打印機(jī),那么我們還需要在Person.h中定義一種操作這種打印機(jī)的方法,那么后續(xù)如果在添加新的打印機(jī)呢?還在添加方法嗎?那么Person.h文件就會變得很臃腫。所以這時候多態(tài)就體現(xiàn)到好處了,使用父類類型,在Person.h中定義一個方法就可以了:
| 1 | -?(void)?doPrint:(Printer?*)printer; |
這里看到了,這個方法的參數(shù)類型就是父類的類型,這就是多態(tài),定義類型為父類類型,實(shí)際類型為子類類型
| 1 2 3 | -?(void)?doPrint:(Printer?*)printer{?? ????[printer?print];?? } |
這里調(diào)用print方法,就是傳遞進(jìn)來的實(shí)際類型的print方法。
| 1 2 3 4 5 | Printer?*p1?=?[[ColorPrinter?alloc]?init];?? Printer?*p2?=?[[BlackPrinter?alloc]?init];?? ??????????? [person?doPrint:p1];?? [person?doPrint:p2]; |
這里的p1,p2表面上的類型是Printer,但是實(shí)際類型是子類類型,所以會調(diào)用他們自己對應(yīng)的print方法。
從上面的例子中我們就可以看到多態(tài)的特新很是重要,當(dāng)然也是三大特性中比較難理解的,但是在coding的過程中,用多了就自然理解了,沒必要去刻意的理解。
微信掃一掃 訂閱每日移動開發(fā)及APP推廣熱點(diǎn)資訊公眾號:CocoaChina 我要投稿??收藏文章 分享到: 29 上一篇:imageIO完成漸進(jìn)加載圖片 下一篇:怎樣做一個iOS App的啟動分層引導(dǎo)動畫?
相關(guān)資訊
- 如何在iOS上創(chuàng)建矢量圖形
- iOS開發(fā)--處理不等高TableViewCell的小花招
- 小白如何晉級入門級iOS開發(fā)者
- iOS runtime實(shí)戰(zhàn)應(yīng)用:成員變量和屬性
- 解決3D Touch導(dǎo)致系統(tǒng)相冊崩潰的問題
- iOS開發(fā)編碼建議與編程經(jīng)驗(yàn)(持續(xù)更新中)
- iOS開發(fā)調(diào)試技巧總結(jié)(持續(xù)更新中)
- iOS開發(fā)-CALayer的探究應(yīng)用
- Unrecognized Selector Sent to Instance問題
- 深入淺出-iOS函數(shù)式編程的實(shí)現(xiàn) && 響應(yīng)式編程概念
熱門資訊
綜合評論
相關(guān)帖子
sinaweixinmail回到頂部 關(guān)于我們?商務(wù)合作?聯(lián)系我們?合作伙伴?2016 Chukong Technologies,Inc.京ICP備 11006519號 京ICP證 100954號?京公網(wǎng)安備11010502020289??京網(wǎng)文[2012]0426-138號
轉(zhuǎn)載于:https://www.cnblogs.com/iOS-mt/p/5601202.html
總結(jié)
以上是生活随笔為你收集整理的多态---父指针指向子类对象(父类引用指向子类对象)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计量注册师考试一些关于期限、时间、机构的
- 下一篇: Redhat、centos安装配置pos