生活随笔
收集整理的這篇文章主要介紹了
类的三大特性
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
類有三大特性:繼承,封裝,多態(tài),這個(gè)也是介紹類的時(shí)候,必須提到的話題,那么今天就來看一下OC中類的三大特性:
一、封裝
學(xué)習(xí)過Java中類的同學(xué)可能都知道了,封裝就是對類中的一些字段,方法進(jìn)行保護(hù),不被外界所訪問到,有一種權(quán)限的控制功能,Java中有四種訪問權(quán)限修飾符:public,default,protected,private,訪問權(quán)限一次遞減的,這樣我們在定義類的時(shí)候,哪些字段和方法不想暴露出去,哪些字段和方法可以暴露,可以通過修飾符來完成,這就是封裝,下面來看一個(gè)例子吧:
Car.h
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? #import?<Foundation/Foundation.h>?? ?? @interface?Car?:?NSObject{?? ?????? ?????? ?????? ?????? @public?? ????float?_capcity;??? }?? ?? -?(void)run:(float)t;?? ?? @end?? 這里我們可以看到,OC中也是有四種訪問權(quán)限修飾符:
?
@public、@protected、@private、@package
其中默認(rèn)的修飾符是@private
但是這里要注意的是:OC中的方法是沒有修飾符的概念的,這個(gè)和Java有很大的區(qū)別,一般都是公開訪問的,即public的,但是我們怎么做到讓OC中的一個(gè)方法不能被外界訪問呢?
OC中是這么做的,如果想讓一個(gè)方法不被外界訪問的話,只需要在.m文件中實(shí)現(xiàn)這個(gè)方法,不要在頭文件中進(jìn)行定義,說白了就是:該方法有實(shí)現(xiàn),沒定義,這樣外界在導(dǎo)入頭文件的時(shí)候,是沒有這個(gè)方法的,但是這個(gè)方法我們可以在自己的.m文件中進(jìn)行使用。
為什么要介紹這點(diǎn)知識呢?因?yàn)樵诤竺嫖覀儠?huì)說到單利模式,到時(shí)候就會(huì)用到這個(gè)知識點(diǎn)了。
二、繼承
繼承是類中的一個(gè)重要的特性,他的出現(xiàn)使得我們沒必要?jiǎng)e寫重復(fù)的代碼,可重用性很高。當(dāng)然OC中的繼承和Java中是一樣的,沒多大區(qū)別,這里在看一個(gè)例子吧:
首先來看一下父類:Car
Car.h
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?<Foundation/Foundation.h>?? ?? @interface?Car?:?NSObject{?? ????NSString?*_brand;?? ????NSString?*_color;?? }?? ?? -?(void)setBrand:(NSString?*)brand;?? -?(void)setColor:(NSString?*)color;?? -?(void)brake;?? -?(void)quicken;?? ?? @end?? 在Car類中定義了兩個(gè)屬性,以及一些方法
?
Car.m
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #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
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?"Car.h"?? ?? @interface?Taxi?:?Car{?? ????NSString?*_company;?? }?? ?? ?? -?(void)printTick;?? ?? @end?? 看到Taxi類繼承了父類Car,這里需要導(dǎo)入父類的頭文件,然后在Taxi類中多了一個(gè)屬性和方法
?
Taxi.m
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #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)用父類的方法,同時(shí)這里我們也是可以用self關(guān)鍵字來調(diào)用,這里看到其實(shí)這兩種方式調(diào)用的效果是一樣的,當(dāng)我們在子類重新實(shí)現(xiàn)brake方法的時(shí)候(Java中的重寫概念),那么這時(shí)候super關(guān)鍵字調(diào)用的還是父類的方法,而self調(diào)用的就是重寫之后的brake方法了。同樣,我們也是可以使用父類中的屬性。
?
再看一下另外一個(gè)子類:
Truck.h
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?"Car.h"?? ?? @interface?Truck?:?Car{?? ????float?_maxWeight;?? }?? ?? ?? ?? -?(void)brake;?? ?? -?(void)unload;?? ?? @end?? 這里就自己定義了一個(gè)brake方法,這時(shí)候就會(huì)覆蓋父類中的brake方法了。
?
Truck.m
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?"Truck.h"?? ?? @implementation?Truck?? ?? -?(void)brake{?? ????[super?brake];?? ????NSLog(@"Truck類中的brake方法");?? }?? ?? -?(void)unload{?? ????[super?brake];?? ????[self?brake];?? ????NSLog(@"%@的卡車卸貨了,載貨量:%.2f,汽車的顏色:%@",_brand,_maxWeight,_color);?? }?? ?? @end?? 這里就可以看到,我們會(huì)在brake方法中調(diào)用一下父類的brake方法,然后在實(shí)現(xiàn)我們自己的邏輯代碼。
?
好了,繼承就說這么多了,其實(shí)封裝和繼承兩個(gè)特性沒什么難度的,很容易理解的,下面在來看一下最后一個(gè)特性:多態(tài)
三、多態(tài)
多態(tài)對于面向?qū)ο笏枷雭碚f,個(gè)人感覺是真的很重要,他對以后的編寫代碼的優(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
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?<Foundation/Foundation.h>?? ?? @interface?Printer?:?NSObject?? ?? -?(void)?print;?? ?? @end?? 就是一個(gè)簡單的方法print
?
Printer.m
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?"Printer.h"?? ?? @implementation?Printer?? ?? -?(void)print{?? ????NSLog(@"打印機(jī)打印紙張");?? }?? ?? @end?? 實(shí)現(xiàn)也是很簡單的
?
下面來看一下具體的子類
ColorPrinter.h
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?"Printer.h"?? ?? ?? @interface?ColorPrinter?:?Printer?? -?(void)print;?? @end?? ?
ColorPrinter.m
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?"ColorPrinter.h"?? ?? @implementation?ColorPrinter?? ?? -?(void)print{?? ????NSLog(@"彩色打印機(jī)");?? }?? ?? @end??
在看一下另外一個(gè)子類
?
BlackPrinter.h
?
[java]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?"Printer.h"?? ?? @interface?BlackPrinter?:?Printer?? ?? -?(void)print;?? ?? @end??
BlackPrinter.m
?
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?"BlackPrinter.h"?? ?? @implementation?BlackPrinter?? ?? -?(void)print{?? ????NSLog(@"黑白打印機(jī)");?? }?? ?? @end?? ?
這里我們在定義一個(gè)Person類,用來操作具體的打印機(jī)
Person.h
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?<Foundation/Foundation.h>?? ?? #import?"ColorPrinter.h"?? #import?"BlackPrinter.h"?? ?? ?? ?? ?? @interface?Person?:?NSObject{?? ????NSString?*_name;?? }?? ?? ?? ?? ?? ?? -?(void)?doPrint:(Printer?*)printer;?? ?? @end?? ?
Person.m
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?"Person.h"?? ?? @implementation?Person?? ?? ? ? ? ? ? ? ? ? ?? ?? -?(void)?doPrint:(Printer?*)printer{?? ????[printer?print];?? }?? ?? @end??
再來看一下測試代碼:
?
main.m
?
[objc]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? #import?<Foundation/Foundation.h>?? ?? #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];?? ?????????? ?????????? ????????? ? ? ? ? ? ?? ?????????? ?????????? ????????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)的好處
上面的例子是一個(gè)彩色打印機(jī)和黑白打印機(jī)這兩種打印機(jī),然后Person類中有一個(gè)操作打印的方法,當(dāng)然這個(gè)方法是需要打印機(jī)對象的,如果不用多態(tài)機(jī)制實(shí)現(xiàn)的話(Person.h中注釋的代碼部分),就是給兩種打印機(jī)單獨(dú)定義個(gè)操作的方法,然后在Person.m(代碼中注釋的部分)中用具體的打印機(jī)對象進(jìn)行操作,在main.m文件中,我們看到,當(dāng)Person需要使用哪個(gè)打印機(jī)的時(shí)候,就去調(diào)用指定的方法:
?
[objc]?view plaincopy
[person?printWithBlack:blackPrint];?? [person?printWithColor:colorPrint];?? 這種設(shè)計(jì)就不好了,為什么呢?假如現(xiàn)在又有一種打印機(jī),那么我們還需要在Person.h中定義一種操作這種打印機(jī)的方法,那么后續(xù)如果在添加新的打印機(jī)呢?還在添加方法嗎?那么Person.h文件就會(huì)變得很臃腫。所以這時(shí)候多態(tài)就體現(xiàn)到好處了,使用父類類型,在Person.h中定義一個(gè)方法就可以了:
?
?
[objc]?view plaincopy
-?(void)?doPrint:(Printer?*)printer;?? 這里看到了,這個(gè)方法的參數(shù)類型就是父類的類型,這就是多態(tài),定義類型為父類類型,實(shí)際類型為子類類型
?
?
[java]?view plaincopy
-?(void)?doPrint:(Printer?*)printer{?? ????[printer?print];?? }?? 這里調(diào)用print方法,就是傳遞進(jìn)來的實(shí)際類型的print方法。
?
?
[objc]?view plaincopy
Printer?*p1?=?[[ColorPrinter?alloc]?init];?? Printer?*p2?=?[[BlackPrinter?alloc]?init];?? ?????????? [person?doPrint:p1];?? [person?doPrint:p2];?? 這里的p1,p2表面上的類型是Printer,但是實(shí)際類型是子類類型,所以會(huì)調(diào)用他們自己對應(yīng)的print方法。
?
從上面的例子中我們就可以看到多態(tài)的特新很是重要,當(dāng)然也是三大特性中比較難理解的,但是在coding的過程中,用多了就自然理解了,沒必要去刻意的理解。
總結(jié)
這篇文章主要介紹了類的三大特性:封裝、繼承、多態(tài),這三個(gè)特性也是后面學(xué)習(xí)面向?qū)ο蟮闹匾A(chǔ)。
?
轉(zhuǎn)載于:https://www.cnblogs.com/ZhenShi/p/5027222.html
總結(jié)
以上是生活随笔為你收集整理的类的三大特性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。