
版權(quán)聲明:本文為作者原創(chuàng)文章,可以隨意轉(zhuǎn)載,但必須在明確位置標(biāo)明出處!!!
文章講到這里,我不得不想先把面向?qū)ο蟮木幊讨v了,否則我們的代碼看上去將會(huì)越來(lái)越亂,越來(lái)也不易管理。
什么是類(lèi)
類(lèi)是對(duì)現(xiàn)實(shí)生活中一類(lèi)具有共同特征的事物的抽象。所有的事物都來(lái)源于生活,不管哪行哪業(yè)都是為了解決我們生活中的問(wèn)題,編程亦是。
類(lèi)的三大屬性
- 封裝:類(lèi)將具有共同特征的一類(lèi)事物抽象在一起,比如水果類(lèi)包含蘋(píng)果、香蕉、梨子、西瓜等等,這些具有同樣屬性的我們可以歸為到一個(gè)類(lèi)里

- 繼承:類(lèi)是有繼承關(guān)系的,繼承關(guān)系的作用是讓子類(lèi)具有自己特有的行為,不如西瓜是它是繼承水果的,那么西瓜它可以定義自己特有的行為、屬性,像有籽西瓜、無(wú)籽西瓜兩種屬性,子類(lèi)可以繼承父類(lèi)的公有方法和屬性。什么意思呢,就像你可以繼承你爸媽的財(cái)產(chǎn),但是你不能繼承你爸媽的朋友,或隱私方面的東西,隱私方面的東西在編程語(yǔ)言中我們稱(chēng)之為private(私有的),私有的東西子女是不可以繼承的。還有一點(diǎn)就是繼承可以是多層級(jí)結(jié)構(gòu)的,就像你可以繼承你爸媽的財(cái)產(chǎn),你兒子也能繼承你的財(cái)產(chǎn),那么你兒子的財(cái)產(chǎn)就包含了你的和爸媽的財(cái)產(chǎn)。

- 多態(tài):從字面意思理解就是多鐘形態(tài),專(zhuān)業(yè)的解釋就是:多態(tài)性是允許你將父對(duì)象設(shè)置成為一個(gè)或更多的他的子對(duì)象相等的技術(shù),賦值之后,父對(duì)象就可以根據(jù)當(dāng)前賦值給它的子對(duì)象的特性以不同的方式運(yùn)作。專(zhuān)業(yè)解釋我想信大多初學(xué)者都不明白啥意思。舉個(gè)例子:某公司A和幾個(gè)快遞服務(wù)公司有合作關(guān)系,比如順風(fēng)、中通、申通。順風(fēng)快遞給A公司打電話(huà)說(shuō)你們公司今年的快件服務(wù)我包了,那么從簽訂合同日起,A公司的所有快遞服務(wù)都會(huì)自動(dòng)的通過(guò)順風(fēng)快遞走,同理,明年若是中通簽了合同,那么A公司明年的快遞服務(wù)都自動(dòng)的走中通快遞服務(wù)。我相信講到這里大家應(yīng)該能明白多態(tài)是什么意思了,多態(tài)說(shuō)百了就是種接口服務(wù)。就像公司A它提供了一個(gè)快遞服務(wù)接口,那么只要是快遞公司都可以去調(diào)用這個(gè)接口。調(diào)用接口后就按照自己公司的物流走就是了。

類(lèi)的定義
class myclass(object):
class_suite
類(lèi)的定義主要是使用關(guān)鍵字「class」,類(lèi)定義好了以后可以在類(lèi)里定義方法,變量;專(zhuān)業(yè)術(shù)語(yǔ)稱(chēng)之為行為,屬性。
類(lèi)的繼承
class A(object):
def foo(self):
print('this is A')
class B(A):
pass
class C(B):
pass
if __name__ == '__main__':
cc = C()
cc.foo()
類(lèi)C繼承類(lèi)B,類(lèi)B繼承類(lèi)A,pass關(guān)鍵字的意思是什么也不做,在類(lèi)中定義方法第一個(gè)參數(shù)都是self,表示類(lèi)本身,如果你接觸過(guò)C/C++語(yǔ)言,那么這里的self就跟C/C++語(yǔ)言里的this指針一個(gè)意思。
- 「if _name_ == '_main_'」:這一句是入口函數(shù),當(dāng)我們運(yùn)行該程序時(shí)解釋器從這里開(kāi)始執(zhí)行。
- 「cc = C()」:創(chuàng)建一個(gè)C類(lèi)型的實(shí)例,只有創(chuàng)建了實(shí)例才能去調(diào)用類(lèi)中的方法和屬性,
- 「cc.foo()」: 這一句就充分體現(xiàn)了類(lèi)的繼承關(guān)系, 類(lèi)C沒(méi)有定義foo()方法,當(dāng)時(shí)它繼承了B,B又繼承了A,所以C自然也就繼承了A的foo方法,這就是繼承的好處,如果父類(lèi)提供了你需要的方法,你就不需要再去重復(fù)定義實(shí)現(xiàn)了。
繼承中的覆蓋(Overriding)
繼承中的覆蓋是什么意思呢,如果類(lèi)B也要實(shí)現(xiàn)方法foo,當(dāng)時(shí)它的方法和類(lèi)A的行為是不是一樣的,那我們就稱(chēng)這種行為為覆蓋
class A(object):
def foo(self):
print('this is A')
class B(A):
def foo(self):
print('this is B')
class C(B):
def foo(self):
print('this is C')
if __name__ == '__main__':
cc = C()
cc.foo()
結(jié)果將會(huì)輸出‘this is C’,類(lèi)C中的foo方法就是C類(lèi)特有的行為。那么到這里有認(rèn)真思考過(guò)的同學(xué)就要問(wèn),我又想有自己的行為,也想調(diào)用父類(lèi)的行為怎么辦呢,看下面的代碼
class A(object):
def foo(self):
print('this is A')
class B(A):
def foo(self):
A.foo(self)
print('this is B')
class C(B):
def foo(self):
B.foo(self)
print('this is C')
if __name__ == '__main__':
cc = C()
cc.foo()
執(zhí)行的結(jié)果將會(huì)輸出
this is A
this is B
this is C
super的使用
上面例子的寫(xiě)法雖然可以達(dá)到目的,但不是一種好的寫(xiě)法,它的不好之處在于若在你的工程中有大量的此種寫(xiě)法,那么若是類(lèi)的繼承關(guān)系變了,那你不得不在整個(gè)工程中去查找修改相應(yīng)的代碼,這里我們使用super的方式改寫(xiě)它。
class A(object):
def foo(self):
print('this is A')
class B(A):
def foo(self):
super(B, self).foo()
print('this is B')
class C(B):
def foo(self):
super(C, self).foo()
print('this is C')
if __name__ == '__main__':
cc = C()
cc.foo()
輸出的結(jié)果和上面一致,使用super()的漂亮之處在于,你不需要明確給出任何基類(lèi)名字...“跑腿事兒”,它幫你干了!使用super()的重點(diǎn),是你不需要明確提供父類(lèi)。這意味著如果你改變了類(lèi)繼承關(guān)系,你只需要改一行代碼(class 語(yǔ)句本身)而不必在大量代碼中去查找所有被修改的那個(gè)類(lèi)的名字。
構(gòu)造器init()
構(gòu)造器也叫構(gòu)造函數(shù),當(dāng)一個(gè)類(lèi)實(shí)例化的時(shí)候它將會(huì)自動(dòng)調(diào)用該函數(shù),這里我們需要提點(diǎn)的是,在python中類(lèi)B繼承了類(lèi)A,他們都實(shí)現(xiàn)了_init_()函數(shù),那么當(dāng)類(lèi)B實(shí)例化的時(shí)候不會(huì)去調(diào)用類(lèi)A的構(gòu)造方法了,這個(gè)和C/C++,JAVA語(yǔ)言是不同的,大家要注意這點(diǎn)
class A(object):
def __init__(self):
print('this is A init')
def foo(self):
print('this is A')
class B(A):
def __init__(self):
print('this is B init')
def foo(self):
super(B, self).foo()
print('this is B')
class C(B):
def __init__(self):
print('this is C init')
def foo(self):
super(C, self).foo()
print('this is C')
if __name__ == '__main__':
cc = C()
cc.foo()
執(zhí)行結(jié)果將會(huì)輸出
this is C init
this is A
this is B
this is C
可以看到它并沒(méi)有去調(diào)用A,B類(lèi)的構(gòu)造器init()方法,如果C不定義會(huì)輸出什么大家可以自己去試試
私有屬性,私有方法
在python中,類(lèi)中的所有方法和屬性默認(rèn)是‘public’共有的,可以被繼承的,那么如果想要屬性和方法不能被繼承怎么辦呢,那就是在屬性和方法的定義前加兩個(gè)下劃線(xiàn), 特別需要提點(diǎn)的是我們自己內(nèi)中定義的函數(shù)不要有想_xxx_()這種定義,這種定義是python內(nèi)建函數(shù)的定義,切記、切記。
class A(object):
def __foo(self):
print('this is A')
class B(A):
pass
class C(B):
pass
if __name__ == '__main__':
print(dir(C))
cc = C()
cc.__foo()
執(zhí)行結(jié)果將會(huì)出現(xiàn)下面錯(cuò)誤
Traceback (most recent call last):
File "classtest.py", line 16, in <module>
cc.__foo()
AttributeError: 'C' object has no attribute '__foo'
多態(tài)的實(shí)現(xiàn)
下面我們將實(shí)現(xiàn)一個(gè)多態(tài)的例子來(lái)結(jié)束本章的內(nèi)容,例子的來(lái)源還是用上面提供的快遞服務(wù)
class Company(object):
#提供一個(gè)快遞服務(wù)接口
def express_service(self, express_company):
express_company.send()
#順風(fēng)快遞公司
class FS(Company):
def send(self):
print('welcome to express by FS')
#中通跨地公司
class ZT(Company):
def send(self):
print('welcome to express by ZT')
#申通跨地公司
class ST(Company):
def send(self):
print('welcome to express by ST')
if __name__ == '__main__':
service = Company()
#使用FS快遞服務(wù)
fs = FS()
service.express_service(fs)
#使用ZT快遞服務(wù)
zt = ZT()
service.express_service(zt)
#使用ST快遞服務(wù)
st = ST()
service.express_service(st)
各位若是初學(xué)者一定要敲代碼,去執(zhí)行,去體會(huì)一下類(lèi)的三大屬性
note: 初學(xué)者最容易犯的錯(cuò)就是書(shū)面上看著挺簡(jiǎn)單的啊,把書(shū)一關(guān)上就懵了,想要成為一個(gè)程序員,一定要多去敲代碼,切記,切記