面向对象初识④
?
?
抽象類與接口類
?
接口類
?
繼承有兩種用途:
?
一:繼承基類的方法,并且做出自己的改變或者擴展(代碼重用) ?
?
二:聲明某個子類兼容于某基類,定義一個接口類Interface,接口類中定義了一些接口名(就是函數(shù)名)且并未實現(xiàn)接口的功能,子類繼承接口類,并且實現(xiàn)接口中的功能
# 一:這樣不好,我要統(tǒng)一一下支付的規(guī)則.class QQpay:def pay(self,money):print('使用qq支付%s元' % money)class Alipay:def pay(self,money):print('使用阿里支付%s元' % money)a = Alipay() a.pay(100)b = QQpay() b.pay(200)# 二,統(tǒng)一支付的規(guī)則 歸一化設計,統(tǒng)一 pay接口 class QQpay:def pay(self,money):print('使用qq支付%s元' % money)class Alipay:def pay(self,money):print('使用阿里支付%s元' % money)def pay(obj,money):obj.pay(money)a = Alipay() b = QQpay()pay(a,100) pay(b,200)# 三,但是,來了一個野生程序員,他不知道你的約定俗成的規(guī)則,就會出問題class QQpay:def pay(self,money):print('使用qq支付%s元' % money)class Alipay:def pay(self,money):print('使用阿里支付%s元' % money)class Wechatpay:def fuqian(self,money):print('使用微信支付%s元' % money)def pay(obj,money):obj.pay(money)a = Alipay() b = QQpay()pay(a,100) pay(b,200)c = Wechatpay() c.fuqian(300)# 四,解決方式 # 定義一個父類,什么都不寫,只是要求繼承我的所有類有一個pay方法,這樣就制定了一個規(guī)范,這就叫做接口類,后者抽象類. class Payment:def pay(self):passclass QQpay(Payment):def pay(self,money):print('使用qq支付%s元' % money)class Alipay(Payment):def pay(self,money):print('使用阿里支付%s元' % money)class Wechatpay(Payment):def fuqian(self,money):print('使用微信支付%s元' % money)def pay(obj,money):obj.pay(money)a = Alipay() b = QQpay()pay(a,100) pay(b,200)c = Wechatpay() c.fuqian(300)#五,他還是不知道看你這些都繼承了一個類,所以你要制定一個規(guī)范,強制他執(zhí)行. # 創(chuàng)建一個規(guī)范 from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): # 抽象類 接口類 規(guī)范和約束 metaclass指定的是一個元類 @abstractmethoddef pay(self):pass # 抽象方法class Alipay(Payment):def pay(self,money):print('使用支付寶支付了%s元'%money)class QQpay(Payment):def pay(self,money):print('使用qq支付了%s元'%money)class Wechatpay(Payment):# def pay(self,money):# print('使用微信支付了%s元'%money)def recharge(self):passdef pay(a,money):a.pay(money)a = Alipay() a.pay(100) pay(a,100) # 歸一化設計:不管是哪一個類的對象,都調用同一個函數(shù)去完成相似的功能 q = QQpay() q.pay(100) pay(q,100) w = Wechatpay() pay(w,100) # 到用的時候才會報錯# 抽象類和接口類做的事情 :建立規(guī)范 # 制定一個類的metaclass是ABCMeta, # 那么這個類就變成了一個抽象類(接口類) # 這個類的主要功能就是建立一個規(guī)范實踐中,繼承的第一種含義意義并不很大,甚至常常是有害的。因為它使得子類與基類出現(xiàn)強耦合。
繼承的第二種含義非常重要。它又叫“接口繼承”。
接口繼承實質上是要求“做出一個良好的抽象,這個抽象規(guī)定了一個兼容接口,使得外部調用者無需關心具體細節(jié),可一視同仁的處理實現(xiàn)了特定接口的所有對象”——這在程序設計上,叫做歸一化。
歸一化使得高層的外部使用者可以不加區(qū)分的處理所有接口兼容的對象集合——就好象linux的泛文件概念一樣,所有東西都可以當文件處理,不必關心它是內存、磁盤、網(wǎng)絡還是屏幕(當然,對底層設計者,當然也可以區(qū)分出“字符設備”和“塊設備”,然后做出針對性的設計:細致到什么程度,視需求而定)。
依賴倒置原則: 高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該應該依賴細節(jié);細節(jié)應該依賴抽象。換言之,要針對接口編程,而不是針對實現(xiàn)編程在python中根本就沒有一個叫做interface的關鍵字,上面的代碼只是看起來像接口,其實并沒有起到接口的作用,子類完全可以不用去實現(xiàn)接口?,如果非要去模仿接口的概念,可以借助第三方模塊:
http://pypi.python.org/pypi/zope.interface
twisted的twisted\internet\interface.py里使用zope.interface
文檔https://zopeinterface.readthedocs.io/en/latest/
設計模式:https://github.com/faif/python-patterns
接口提取了一群類共同的函數(shù),可以把接口當做一個函數(shù)的集合。然后讓子類去實現(xiàn)接口中的函數(shù)。這么做的意義在于歸一化,什么叫歸一化,就是只要是基于同一個接口實現(xiàn)的類,那么所有的這些類產(chǎn)生的對象在使用時,從用法上來說都一樣。歸一化,讓使用者無需關心對象的類是什么,只需要的知道這些對象都具備某些功能就可以了,這極大地降低了使用者的使用難度。比如:我們定義一個動物接口,接口里定義了有跑、吃、呼吸等接口函數(shù),這樣老鼠的類去實現(xiàn)了該接口,松鼠的類也去實現(xiàn)了該接口,由二者分別產(chǎn)生一只老鼠和一只松鼠送到你面前,即便是你分別不到底哪只是什么鼠你肯定知道他倆都會跑,都會吃,都能呼吸。再比如:我們有一個汽車接口,里面定義了汽車所有的功能,然后由本田汽車的類,奧迪汽車的類,大眾汽車的類,他們都實現(xiàn)了汽車接口,
這樣就好辦了,大家只需要學會了怎么開汽車,那么無論是本田,還是奧迪,還是大眾我們都會開了,開的時候根本無需關心我開的是哪一類車,
操作手法(函數(shù)調用)都一樣
抽象類
什么是抽象類
? ? 與java一樣,python也有抽象類的概念但是同樣需要借助模塊實現(xiàn),抽象類是一個特殊的類,它的特殊之處在于只能被繼承,不能被實例化
為什么要有抽象類
??? 如果說類是從一堆對象中抽取相同的內容而來的,那么抽象類就是從一堆類中抽取相同的內容而來的,內容包括數(shù)據(jù)屬性和函數(shù)屬性。
比如我們有香蕉的類,有蘋果的類,有桃子的類,從這些類抽取相同的內容就是水果這個抽象的類,你吃水果時,要么是吃一個具體的香蕉,要么是吃一個具體的桃子。。。。。。你永遠無法吃到一個叫做水果的東西。
? ? 從設計角度去看,如果類是從現(xiàn)實對象抽象而來的,那么抽象類就是基于類抽象而來的。
從實現(xiàn)角度來看,抽象類與普通類的不同之處在于:抽象類中有抽象方法,該類不能被實例化,只能被繼承,且子類必須實現(xiàn)抽象方法。這一點與接口有點類似,但其實是不同的,即將揭曉答案
抽象類與接口類
抽象類的本質還是類,指的是一組類的相似性,包括數(shù)據(jù)屬性(如all_type)和函數(shù)屬性(如read、write),而接口只強調函數(shù)屬性的相似性。
抽象類是一個介于類和接口直接的一個概念,同時具備類和接口的部分特性,可以用來實現(xiàn)歸一化設計?
在python中,并沒有接口類這種東西,即便不通過專門的模塊定義接口,我們也應該有一些基本的概念。
1.多繼承問題
在繼承抽象類的過程中,我們應該盡量避免多繼承;
而在繼承接口的時候,我們反而鼓勵你來多繼承接口
2.方法的實現(xiàn)
在抽象類中,我們可以對一些抽象方法做出基礎實現(xiàn);
而在接口類中,任何方法都只是一種規(guī)范,具體的功能需要子類實現(xiàn)
多態(tài)
Pyhon不支持Java和C#這一類強類型語言中多態(tài)的寫法,但是原生多態(tài),其Python崇尚“鴨子類型”。
class F1:passclass S1(F1):def show(self):print 'S1.show'class S2(F1):def show(self):print 'S2.show'# 由于在Java或C#中定義函數(shù)參數(shù)時,必須指定參數(shù)的類型 # 為了讓Func函數(shù)既可以執(zhí)行S1對象的show方法,又可以執(zhí)行S2對象的show方法,所以,定義了一個S1和S2類的父類 # 而實際傳入的參數(shù)是:S1對象和S2對象def Func(F1 obj):"""Func函數(shù)需要接收一個F1類型或者F1子類的類型"""print obj.show()s1_obj = S1() Func(s1_obj) # 在Func函數(shù)中傳入S1類的對象 s1_obj,執(zhí)行 S1 的show方法,結果:S1.show s2_obj = S2() Func(s2_obj) # 在Func函數(shù)中傳入Ss類的對象 ss_obj,執(zhí)行 Ss 的show方法,結果:S2.show Python偽代碼實現(xiàn)Java或C#的多態(tài) class F1:passclass S1(F1):def show(self):print 'S1.show'class S2(F1):def show(self):print 'S2.show'def Func(obj):print obj.show()s1_obj = S1() Func(s1_obj) s2_obj = S2() Func(s2_obj) Python “鴨子類型”封裝
封裝,顧名思義就是將內容封裝到某個地方,以后再去調用被封裝在某處的內容。
所以,在使用面向對象的封裝特性時,需要:
- 將內容封裝到某處
- 從某處調用被封裝的內容
第一步:將內容封裝到某處
self 是一個形式參數(shù),當執(zhí)行 obj1 = Foo('wupeiqi', 18 ) 時,self 等于 obj1
? ? ? ? ? ? ? ? ? ? ? ? ? ? ??當執(zhí)行 obj2 = Foo('alex', 78 ) 時,self 等于 obj2
所以,內容其實被封裝到了對象 obj1 和 obj2 中,每個對象中都有 name 和 age 屬性,在內存里類似于下圖來保存。
?
第二步:從某處調用被封裝的內容
調用被封裝的內容時,有兩種情況:
- 通過對象直接調用
- 通過self間接調用
1、通過對象直接調用被封裝的內容
上圖展示了對象 obj1 和 obj2 在內存中保存的方式,根據(jù)保存格式可以如此調用被封裝的內容:對象.屬性名
1 class Foo: 2 3 def __init__(self, name, age): 4 self.name = name 5 self.age = age 6 7 obj1 = Foo('wupeiqi', 18) 8 print obj1.name # 直接調用obj1對象的name屬性 9 print obj1.age # 直接調用obj1對象的age屬性 10 11 obj2 = Foo('alex', 73) 12 print obj2.name # 直接調用obj2對象的name屬性 13 print obj2.age # 直接調用obj2對象的age屬性2、通過self間接調用被封裝的內容
執(zhí)行類中的方法時,需要通過self間接調用被封裝的內容
class Foo:def __init__(self, name, age):self.name = nameself.age = agedef detail(self):print self.nameprint self.ageobj1 = Foo('wupeiqi', 18) obj1.detail() # Python默認會將obj1傳給self參數(shù),即:obj1.detail(obj1),所以,此時方法內部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18 obj2 = Foo('alex', 73) obj2.detail() # Python默認會將obj2傳給self參數(shù),即:obj1.detail(obj2),所以,此時方法內部的 self = obj2,即:self.name 是 alex ; self.age 是 78綜上所述,對于面向對象的封裝來說,其實就是使用構造方法將內容封裝到 對象 中,然后通過對象直接或者self間接獲取被封裝的內容。
?
轉載于:https://www.cnblogs.com/caisong/p/9254441.html
總結
- 上一篇: 央视:部分芯片价格雪崩 200元降至20
- 下一篇: 对象的克隆