023_接口類,抽象類,多態,鴨子類型,封裝

1,接口類
class Wechat():
    def pay(self,money):
        print('已經用微信支付了%s元'%money)
class Alipay():
    def pay(self,money):
        print('已經用支付寶支付了%s元' % money)
wechat = Wechat()
ali = Alipay()
# wechat.pay(100)
# ali.pay(200)
#將上面兩句用下面的替換,
def pay(pay_obj,money):  # 統一支付入口
    pay_obj.pay(money)
pay(wechat,100)
pay(ali,200)

2,規範化程序java

2.1,問題
  若是來我的接手這個程序,他要添加一個應用支付。但他並不知道你的其它應用支付方法你定義的都是pay方法(程序如上例),且統一支付接口調用pay方法。
  他本身添加的應用支付的支付方法並非用pay命名的。所以,當用統一接口支付時,找不到對應的支付方法,就會報錯。
  例如在上程序添加以下代碼
class Applepay():
    def zhifu(self,money):
        print('已經用applepay支付了%s元' % money)
app = Applepay()
pay(app,100) #報錯
  2.2,解決上問題,
  定義一個父類,並將上面的支付程序都繼承這個父類,當用統一接口調用時,如該應用的支付沒有該方法,就會執行父類的這個pay方法,拋出異常給接受該程序的人看,告訴他,沒有實現這個方法。
class Payment:
	def pay(self,money):
		raise NotImplementedError	#拋出沒有實現這個方法的異常

class Applepay(Payment):
	def zhifu(self,money):
		print('已經用applepay支付了%s元' % money)

def pay(pay_obj,money):  # 統一支付入口
	pay_obj.pay(money)
	
app = Applepay()
pay(app,100)	#報錯
  2.3,解決方法升級,規範化程序
from abc import abstractmethod,ABCMeta
class Payment(metaclass=ABCMeta):       # 元類 默認的元類 type   #metaclass不是繼承,而是指定元類
    @abstractmethod
    def pay(self,money):pass                # 沒有實現這個方法
    經過上面的代碼,寫一個規範程序的父類。將各支付類都繼承該父類。起到規範子類程序的做用。
    這樣接手的人在實例化對象時,就會報錯,並提示少了什麼方法。
app = Applepay()  #報錯
3,抽象類與接口類
              # python中規範化程序稱爲 :接口類或者抽象類均可以
    #在Java中有嚴格區分:
    # 接口類 支持多繼承,接口類中的全部的方法都必須不能實現 —— java
    # 抽象類 不支持多繼承,抽象類中方法能夠有一些代碼的實現 —— java

  抽象類的本質仍是類,指的是一組類的類似性,包括數據屬性(如all_type)和函數屬性(如read、write),而接口只強調函數屬性的類似性。python

  抽象類是一個介於類和接口直接的一個概念,同時具有類和接口的部分特性,能夠用來實現歸一化設計 git

  在python中,並無接口類這種東西,即使不經過專門的模塊定義接口,咱們也應該有一些基本的概念。程序員

 
4,多態
    python沒有多態,由於python天生支持多態
    多態指的是一類事物有多種形態,動物有多種形態:人,狗,豬
import abc
class Animal(metaclass=abc.ABCMeta): #同一類事物:動物
    @abc.abstractmethod
    def talk(self):
        pass
class People(Animal): #動物的形態之一:人
    def talk(self):
        print('say hello')
class Dog(Animal): #動物的形態之二:狗
    def talk(self):
        print('say wangwang')
class Pig(Animal): #動物的形態之三:豬
    def talk(self):
        print('say aoao')
5,鴨子類型
  逗比時刻:
  • Python崇尚鴨子類型,即‘若是看起來像、叫聲像並且走起路來像鴨子,那麼它就是鴨子’ 。
  • python程序員一般根據這種行爲來編寫程序。例如,若是想編寫現有對象的自定義版本,能夠繼承該對象,也能夠建立一個外觀和行爲像,但與它無任何關係的全新對象,後者一般用於保存程序組件的鬆耦合度。
  • 例1:利用標準庫中定義的各類‘與文件相似’的對象,儘管這些對象的工做方式像文件,但他們沒有繼承內置文件對象的方法
  • 例2:序列類型有多種形態:字符串,列表,元組,但他們直接沒有直接的繼承關係
  #兩者都像鴨子,兩者看起來都像文件,於是就能夠當文件同樣去用
class TxtFile:
    def read(self):
        pass
    def write(self):
        pass
class DiskFile: def read(self): pass def write(self): pass
6,封裝
  6.1,封裝的方式
    # 廣義上面向對象的封裝 :代碼的保護,面向對象的思想自己就是一種
    # 只讓本身的對象能調用本身類中的方法
  # 狹義上的封裝 —— 面向對象的三大特性之一
  # 屬性 和 方法都藏起來 不讓你看見
    # 全部的私有 都是在變量的左邊加上雙下劃綫
            # 對象的私有屬性
            # 類中的私有方法
           # 類中的靜態私有屬性
    # 全部的私有的 都不能在類的外部使用
    #在子類定義的__x不會覆蓋在父類定義的__x,由於子類中變造成了:_子類名__x,而父類中變造成了:_父類名__x,即雙下滑線開頭的屬性在繼承給子類時,子類是沒法覆蓋的。
class Person:
    __key = 123  # 私有靜態屬性
    def __init__(self,name,passwd):
        self.name = name
        self.__passwd = passwd   
		# 在變量的左邊加上雙下劃線,就變成私有屬性  #變形爲:_Person__passwd
    def __get_pwd(self):	# 私有方法   #變形爲:_Person__get_pwd
        return self.__passwd   #只要在類的內部使用私有屬性,就會自動的帶上「_類名」,在外部這樣定義不會。
    def login(self):          # 正常的方法調用私有的方法,即只在內部使用
        self.__get_pwd()
alex = Person('alex','alex3714')
print(alex._Person__passwd)   # 「_類名或對象名__屬性名」能夠調出該屬性,可是不要用此方法在外部操做。
# print(alex.get_pwd()) #不可調用

  6.2,能夠設置,get和set方法以便在外部更改查看私有屬性,可能會想爲何要畫蛇添足,不設成私有的不久行了嗎。微信

    這樣寫有它的好處,便可以在get和set方法中加限定條件,以知足要求。因此,若是不須要對外限定保護屬性,能夠不用設定成私有的。app

 
class Room:
    def __init__(self,name,length,width):
        self.__name = name
        self.__length = length
        self.__width = width
    def get_name(self):       #不加限定條件的get
        return self.__name
    def set_name(self,newName):  #加限定條件的set
        if type(newName) is str and newName.isdigit() == False:
            self.__name = newName
        else:
            print('不合法的姓名')
    def area(self):
        return self.__length * self.__width

jin = Room('金老闆',2,1)
print(jin.area())
jin.set_name('2')
print(jin.get_name())

  6.3,假設父類的私有屬性 能被子類調用麼?,不會函數

class Foo:
    __key = '123'       #變形爲: _Foo__key

class Son(Foo):
    print(Foo.__key)     #繼承屬性後變形爲: _Son__key

  6.4,會用到私有的這個概念de場景
    1.隱藏起一個屬性 不想讓類的外部調用
    2.我想保護這個屬性,不想讓屬性隨意被改變
    3.我想保護這個屬性,不被子類繼承微信支付

相關文章
相關標籤/搜索