day25:接口類和抽象類

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()
相關文章
相關標籤/搜索