物件導向 -- 三大特性之繼承 補充 抽象類 介面類

想吃橙子發表於2019-03-28

type 和 class

type 一個物件的時候,結果總是這個物件所屬的類

那麼類是什麼型別?

所有的類的型別都是type

type 是所有型別的鼻祖

type( 類名 ) = type

類也是被創造出來的 可以由python直譯器創造 也可以由特殊的方法創造

常規創造的類 總是有幾個特性

能夠例項化  能有屬性  能有方法一些有特殊需求的類

所有的用class常規語法創造出來的類 都是type型別

元類

能幫你創造出不同尋常的類

可以實現特殊的需求 例如 不能例項化  只能有一個例項

抽象類

類的約束

不同的類,要使用的方法相同,但如果有一個類的方法名字寫錯了 呼叫方法的時候會很麻煩

class Wechatpay:
    def __init__(self,name,money):
        self.name = name
        self.money = money
    def pay(self):
        print('%s通過微信支付了%s元'%(self.name,self.money))

class Alipay:
    def __init__(self,name,money):
        self.name = name
        self.money = money
    def pay(self):
        print('%s通過支付寶支付了%s元'%(self.name,self.money))

class ApplePay:
    def __init__(self,name,money):
        self.name = name
        self.money = money
    def fuqian(self):
        print('%s通過apple pay支付了%s元' % (self.name, self.money))


# 歸一化設計
def pay(person):
    person.pay()


wcp = Wechatpay('alex',2000000)
pay(wcp)
ali = Alipay('alex',2000000)

app = ApplePay('alex',2000000)
pay(app)

程式碼的規範沒有建立起來

所以此時我們要用到對類的約束,對類的約束有兩種:

1. 提取⽗類. 然後在⽗類中定義好⽅法. 在這個⽅法中什麼都不⽤⼲. 就拋⼀個異常就可以了. 這樣所有的⼦類都必須重寫這個⽅法. 否則. 訪問的時候就會報錯. 

2. 使⽤元類來描述⽗類. 在元類中給出⼀個抽象⽅法. 這樣⼦類就不得不給出抽象⽅法的具體實現. 也可以起到約束的效果.

先用第一種方式解決:

class Payment:
    """
    此類什麼都不做,就是制定一個標準,誰繼承我,必須定義我裡面的方法。
    """
    def pay(self,money):
        raise Exception("你沒有實現pay方法")

class 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()
c = Wechatpay()
pay(a,100)
pay(b,200)
pay(c,300)

第二種方法:

引入抽象類的概念處理

from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):    # 抽象類

    @abstractmethod   # 如果我必須要實現pay方法,那麼我需要給pay加一個裝飾器
    def pay(self):
        pass   # 建立的這個pay並沒有內容,
               # 之所以寫一個pay是為了提醒所有子類你一定要實現一個pay方法
               # 如果子類沒有使用這兩個方法,就會報錯
    @abstractmethod
    def back(self):
        pass

class Wechatpay(Payment):
    def __init__(self,name,money):
        self.name = name
        self.money = money
    def pay(self):
        print('%s通過微信支付了%s元'%(self.name,self.money))
    def back(self):
        print('退款')

class Alipay(Payment):
    def __init__(self,name,money):
        self.name = name
        self.money = money
    def pay(self):
        print('%s通過支付寶支付了%s元'%(self.name,self.money))
    def back(self):
        print('退款')

class ApplePay(Payment):
    def __init__(self, name, money):
        self.name = name
        self.money = money
    def pay(self):
        print('%s通過apple pay支付了%s元' % (self.name, self.money))
    def back(self):
        print('退款')


w = Wechatpay('alex',200)
w.pay()

 

from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):    # 抽象類 介面類  規範和約束  metaclass指定的是一個元類
    @abstractmethod
    def 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):pass

def pay(a,money):
    a.pay(money)

a = Alipay()
a.pay(100)
pay(a,100)    # 歸一化設計:不管是哪一個類的物件,都呼叫同一個函式去完成相似的功能
q = QQpay()
q.pay(100)
pay(q,100)
w = Wechatpay()
pay(w,100)   # 到用的時候才會報錯



# 抽象類和介面類做的事情 :建立規範
# 制定一個類的metaclass是ABCMeta,
# 那麼這個類就變成了一個抽象類(介面類)
# 這個類的主要功能就是建立一個規範

總結

約束. 其實就是⽗類對⼦類進⾏約束. ⼦類必須要寫xxx⽅法. 在python中約束的⽅式和⽅法有兩種:

1. 使⽤抽象類和抽象⽅法, 由於該⽅案來源是java和c#. 所以使⽤頻率還是很少的

2. 使⽤⼈為丟擲異常的⽅案. 並且儘量丟擲的是NotImplementError. 這樣比較專業, ⽽且錯誤比較明確.(推薦)

介面類

java中沒有多繼承的類

所以抽象類 只能是所有的子類只有一個規範

於是發明了介面 介面可以多繼承

在python中沒有介面專用語法

只是通過類的多繼承 模仿介面效果

抽象類是單繼承的規範  介面類是多繼承的規範

from abc import ABCMeta,abstractmethod
class NormalAnnimal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):pass

    @abstractmethod
    def drink(self):pass
class FlyAnimal(metaclass=ABCMeta):
    @abstractmethod
    def fly(self):pass

class SwimAnimal(metaclass=ABCMeta):
    @abstractmethod
    def swim(self):pass

class WalkAnimal(metaclass=ABCMeta):
    @abstractmethod
    def walk(self):pass


class Frog(NormalAnnimal,SwimAnimal,WalkAnimal):
    def eat(self):
        pass


class Tiger(NormalAnnimal,SwimAnimal,WalkAnimal):pass
class Swan(NormalAnnimal,FlyAnimal,SwimAnimal,WalkAnimal):pass
class Parrot(NormalAnnimal,FlyAnimal,WalkAnimal):
    def talk(self):
        pass

 

相關文章