1,接口類和抽象類知識背景:一開始在程序界是沒有這些概念的,後來就流行了一種語言叫作JAVA,JAVA是一種典型的純面向對象的語言,JAVA寫的程序都是很是適用於更龐大的項目,不少程序員就總結出了一些設計程序的方式,好比說,這一個程序要實現的是哪一類的問題,給這些問題歸類,實現A問題用一種思路,實現B問題用另一種思路,因而就出現了設計模式,因此設計模式一開始最先的時候是源自於JAVA,後來過了一段時間,這個設計模式在整個程序界火了起來,他很經典,總結了不少經典的問題,後來出了一本書,小黑皮的,最先的時候,也沒有接口的概念,這個接口的概念,來源於設計模式裏,在Python裏,其實Python是一門很特殊的語言,後面多態的時候會具體講特殊在哪兒,由於Python很簡單,有他的簡便性和便捷性,因此你們對於Python要不要設計模式持兩種態度,一種認爲,設計模式是一種經典的設計思想,另外一種認爲,既然源自於JAVA,那麼他可能更適合於JAVA,不那麼適合於Python,因此貶的人貶,推崇的人就很推崇。python
2,抽象類和接口類不少人是分不清楚的,Python原生是不支持接口類的,根本沒有這個概念,可是因爲設計模式裏面有,因此咱們就介紹這個概念。Python原生支持抽象類。他倆在Python裏自己很接近,其餘語言仍是有區別的程序員
3,支付功能編程
class Wechat: def pay(self,money): print('已經用微信支付了%s元'%money) class Alipay: def pay(self,money): print('已經用支付寶支付了%s元'%money) weChat = Wechat() weChat.pay(100) ali = Alipay() ali.pay(200) # 統一支付入口,相似於len函數對比 def pay(pay_obj,money): pay_obj.pay(money) pay(weChat,100) pay(ali,200)
4,添加一個Applepay設計模式
# 這樣添加的支付方式沒有辦法統一了 class Applepay: def fuqian(self,money): print('已經用Applepay支付了%s'%money)
5,這個地方調用的時候會報錯微信
class Payment: def pay(self,money): raise NotImplemented class Wechat(Payment): def pay(self,money): # 父類和子類須要有相同的參數這個函數 print('已經用微信支付了%s元'%money) class Alipay(Payment): def pay(self,money): print('已經用支付寶支付了%s元'%money) class Applepay(Payment): def fuqian(self,money): print('已經用Applepay支付了%s'%money) weChat = Wechat() weChat.pay(100) ali = Alipay() ali.pay(200) apple = Applepay() apple.pay(300) # TypeError: exceptions must derive from BaseException
6,如何不調用就能夠知道這個錯誤呢?app
from abc import abstractmethod,ABCMeta class Payment(metaclass=ABCMeta): # 元類,全部類都有個機制,默認是type,這個機制,支持創造一個類, # 加上這句話,表示我即將要寫一個類的規範了。 # 這一句要求我要實現一個接口類了。 @abstractmethod def pay(self,money):pass # 規範,既能夠說是抽象類,也能夠說是接口類,自己就是一種規範。 class Wechat(Payment): def pay(self,money): # 父類和子類須要有相同的參數這個函數 print('已經用微信支付了%s元'%money) class Alipay(Payment): def pay(self,money): print('已經用支付寶支付了%s元'%money) class Applepay(Payment): def fuqian(self,money): print('已經用Applepay支付了%s'%money) apple = Applepay()
7,接口類,默認多繼承,接口類中的全部的方法都必須不能實現,這個規定是來自於JAVA的,可是若是說在Python裏面硬要實現,也是能夠的,只不過通常狀況下咱們不建議寫函數
8,抽象類,不支持多繼承,儘可能只用單繼承,抽象類中能夠實現一些方法,裏面能夠有一些代碼的實現。二者共同點,就是要規範子類,Python裏面區別不大。一個單繼承,一個多繼承微信支付
9,類是從一堆對象中抽取相同的內容,抽象類是從一堆類中抽取相同的內容,包括數據屬性和函數屬性。抽象類中有抽象方法,該類不能被實例化,只能被繼承,且子類必須實現抽象方法。spa
10,接口類的多繼承和接口隔離原則,想象以前的開放封閉原則,這個例子更相似於接口類,面向對象的方法。操作系統
from abc import abstractmethod,ABCMeta class Swim_Animal(metaclass=ABCMeta): @abstractmethod def swim(self): pass class Walk_Animal(metaclass=ABCMeta): @abstractmethod def walk(self): pass class Fly_Animal(metaclass=ABCMeta): @abstractmethod def fly(self): pass class Tiger(Walk_Animal,Swim_Animal):pass class Eagle(Fly_Animal,Walk_Animal):pass class Swan(Swim_Animal,Walk_Animal,Fly_Animal):pass # 接口類, # 接口隔離原則,編程時的一個原則,使用多個專門的接口,而不是單一的總接口,即客戶端不該該依賴於哪些不須要的接口
11,接口的思想就是,我要實現不一樣的功能,我就去繼承不一樣的接口來規範我當前的類裏面須要有哪些函數。接口類其實沒有的話,也能實現功能,只不過不規範。
12,抽象類的單繼承
13,
# Python裏面一切都是對象,操做系統裏面一切都是文件 import abc class All_file(metaclass=abc.ABCMeta): all_type = "file" # 定義抽象方法,無需實現功能,可是子類必須定義讀寫功能 @abc.abstractmethod def read(self):pass @abc.abstractmethod def write(self):pass # class Txt(All_file):pass # # t1 = Txt() #報錯,子類沒有定義抽象方法 # TypeError: Can't instantiate abstract class Txt with abstract methods read, write class Txt(All_file): # 子類繼承抽象類,可是必須定義read和write方法 def read(self):print('txt read') def write(self):print('txt write') class Sata(All_file): def read(self):print('sata read') def write(self):print('sata write') class Process(All_file): def read(self):print('process read') def write(self):print('process write') wenjianjia = Txt() yingpan = Sata() jincheng = Process() # 這樣你們都被歸一化了,也就是一切皆文件的思想 wenjianjia.read() yingpan.write() jincheng.read() # 通常狀況下 單繼承 能實現的功能都是同樣的,因此在父類中能夠有一些簡單的基礎實現 # 多繼承的狀況,因爲功能比較複雜,因此不容易抽象出相同的功能的具體實現寫在父類中 # 接口類仍是抽象類,面向對象的開發規範 # Python中沒有接口類,Java裏有接口interface這個概念 # Python自帶多繼承,因此咱們直接用class來實現接口類
# Python中支持抽象類:通常狀況下 單繼承 不能實例化 且能夠實現python代碼
14,JAVA裏的全部類的繼承都是單繼承,因此抽象類玩麼的解決了單繼承需求中的規範問題,可是對於多繼承的需求,因爲JAVA自己語法的不支持,因此建立了接口Interface這個概念來解決多繼承的問題。
15,Python天生支持多態,多態,一類事務的多種形態(廣義的多態)向不一樣的對象發送同一個消息,會有不一樣的響應。相同的方法,不一樣對象作的事不一樣,就叫作多態,JAVA裏面想要實現多態,必須有一個共同的父類,纔可實現不一樣的對象調用一樣的方法,傳的對象類型,Python裏面是不須要的,因此這個共同的父類是不須要的,天生支持多態。
16,Python是一門動態強類型的語言,不能直接說強類型,也不能說是弱類型的,弱類型支持 2+‘str'
17,Python裏面不崇尚多態,不須要藉助父類來實現多態。Python崇尚鴨子類型,鴨子類型,補充上根據繼承得來的類似,我只是本身實現我本身的代碼就能夠了,若是兩個類恰好類似,並不產生父類的子類的兄弟關係,而是鴨子類型。這種類似是本身寫代碼約束的,而不是經過父類約束的,優勢:鬆耦合,每一個類似的類之間都沒有影響,缺點:太隨意了,沒有硬性的規範,去必須實現這個功能。只能靠自覺。
18,強類型語言,只能用多態,Python不用實現共同的父類,崇尚鴨子類型。
19,封裝
# 廣義上面向對象的封裝:代碼的保護,面向對象思想的自己就是一種 # 只讓本身的對象能調用本身類中的方法 # 狹義上的封裝 ---面向對象的三大特徵之一 # 屬性和方法都隱藏起來 不讓你看見 class Person: def __init__(self,name,passwd,id): self.name = name self.passwd = passwd self.__id = id alex = Person('alex','alex3714',12) print(alex.passwd) # alex3714 print(alex.__id) # AttributeError: 'Person' object has no attribute '__id'
20,前面加上雙下劃線,就變成私有屬性了,
class Person: def __init__(self,name,passwd,id): self.name = name self.passwd = passwd self.__id = id def get_id(self): return self.__id alex = Person('alex','alex3714',12) print(alex.passwd) # alex3714 # print(alex.__id) # AttributeError: 'Person' object has no attribute '__id' print(alex.__dict__) # {'name': 'alex', 'passwd': 'alex3714', '_Person__id': 12} print(Person.__dict__) print(alex._Person__id) # 12 _類名_屬性名,實際中不能夠這樣用,這是一種投機倒把的方式
21,
alex.__id = 10 # 這樣寫只是給對象新添加了一個屬性 print(alex.passwd) print(alex.__dict__) # {'name': 'alex', 'passwd': 'alex3714', '_Person__id': 12, '__id': 10} print(Person.__dict__)
22,總結:全部的私有 都是在變量的左邊加上雙下劃線:對象的私有屬性,類中的私有方法,類中的靜態私有屬性。全部的私有的都不能在類的外部使用。
23,其餘語言中有public,protected,private,Python中沒有protected,只有public和private,python 裏的私有都是假的,只不過是包了一層而已。只要在類的內部使用私有屬性,就會自動的帶上類名
24,
class Person:
__key = 123 # 類的私有屬性 def __init__(self,name,passwd,id): self.name = name self.passwd = passwd self.__id = id # 私有屬性 def __get_id(self): # 私有方法 return self.__id def login(self): # 只能夠在類的內部使用私有變量 self.__get_id()