自學Python-13 面向對象編程(二、進階篇)


自學Python-13 面向對象編程(二、進階篇)

一個完整的示例,理解什麼是封裝、繼承與多態


<code>class Animal:
"""
雙下劃線 表示屬性私有,外部不能直接訪問,但實際上Python
沒有嚴格語法來限制外部真的不能訪問,你仍然可以通過
animal.Animal__eye來直接訪問,可以看出python只是對私
有屬性改了個名稱來限制我們的訪問。這看起來比較矛盾,駱昊
前輩在這個問題上這樣說,他說“因為絕大多數程序員都認為開放
比封閉要好,而且程序員要自己為自己的行為負責。”私有方法也
是用雙下劃線聲明
"""
__eye = 2

"""
單下劃線 只是暗示該屬性為私有,不建議外接直接訪問,但外部
還是可以直接通過animal._age訪問,意思是:雖然我可以被訪
問,但是,請把我視為私有變量,不要隨意訪問
"""

_age = 8

_leg = 2

def __init__(self, name):
self._name = name

"""
不管使用哪種方式定義私有屬性,如果我們要訪問可以通過getter和setter
來訪問和修改,這其實就是封裝的思想,將不需要外部知道的細節私有化,同
時提供一些可以被外部訪問到的屬性和方法,這樣能很好的減少耦合,自己的
事情自己處理,避免干擾外部業務。
"""

# eye的getter-訪問器
@property
def eye(self):
return self.__eye

# eye的setter-修改器
@eye.setter
def eye(self, eye):
self.__eye = eye

# leg的getter
@property
def leg(self):
return self._leg

"""
我們只為leg屬性設置了訪問器,沒有設置修改器,因此leg在本類中是一個只
讀屬性,實際上我們可以在setter中檢查參數合法性,減少出錯可能性,或者
也可以做其他的處理,這也是封裝的思想體現

"""

"""
定義一個動物叫的方法,方法和函數只是定義和叫法上的不同,沒有大的歧
義。方法就是在類內部的函數
"""

def makeVoice(self):
print('%s是動物,會發出叫聲' % self._name)

"""
staticmethod修飾類的靜態方法,直接通過(類名.靜態方法名調用)。純粹
的功能性方法比較適合聲明為靜態方法,例如在動物類中有一個判斷是不是動
物的靜態方法,這個方法與本類中其他方法沒有任何關聯,這看起來有點像
java工具類中的靜態方法一樣。該方法放在其他類中或者是單獨聲明為一個類
外的函數也可以,但是那樣不利於模塊的劃分,代碼堆在一起會很亂。
"""
@staticmethod
def isAnimal(eye, leg):
# 我假設動物的眼睛不超過2 腿不超過4
if eye > 2 or leg > 4:
return False

"""
classmethod修飾類的類方法,直接通過(類名.類方法名調用)。內置date類
中的類方法就是個很好的示例。


@classmethod
def fromtimestamp(cls, t):
y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
return cls(y, m, d)

@classmethod
def today(cls):
t = _time.time()
return cls.fromtimestamp(t)

"""

# 定義一個寵物類 下面會操作多繼承


class Pet:
def __init__(self, name):
self.__name = name

def sleep(self):
print('%s睡覺' % self.__name)

def makeVoice(self):
print('%s是寵物,會發出叫聲' % self.__name)


# 單繼承 Dog類繼承自Animal類
class Dog(Animal):
def __init__(self, name):
# 調用父類構造方法
Animal.__init__(self, name)
# 子類可以定義自己的屬性
self.__name = name
# 子類繼承了父類的屬性
print('繼承父類的age屬性:%s' % self._age) # 繼承父類的age屬性:8

# 子類重寫父類的方法,表現出不同的行為
def makeVoice(self):
print('%s是狗,會發出汪汪汪的叫聲' % self.__name)


# 子類有更多的能力
def watchDoor(self):
print('狗會看門')


dog = Dog('小黑')
dog.makeVoice() # 小黑是狗,會發出汪汪汪的叫聲
# getter訪問eye
print(dog.eye) # 2
# setter設置eye
dog.eye = 10
print(dog.eye) # 10
# 嘗試修改只讀屬性-會報錯的
# dog.leg = 4 # AttributeError: can't set attribute
# 訪問下雙下劃線定義的eye屬性

"""
多繼承 Cat繼承Animal類和Pet類
需要注意圓括號中父類的順序,若是父類中有相同的方法名,而在子類使用時未指
定,python從左至右搜索 即方法在子類中未找到時,從左到右查找父類中是否包含
方法。例如若Cat中未重寫makeVoice方法,則調用時將調用的Animal中的
makeVoice方法
"""


class Cat(Animal, Pet):
def __init__(self, name):
Animal.__init__(self, name)
Pet.__init__(self, name)
self.__name = name

# 子類重寫父類方法,表現出不同的行為

def makeVoice(self):
print('%s是貓,會發出喵喵喵的叫聲' % self.__name)

/<code>


封裝

將屬性與方法私有化,對外提供接口統一訪問。這一過程將不需要外部知道的細節隱藏起來,同時在類中可自由更改自身的業務邏輯,不與外部發生衝突,能很好的解耦。


繼承

繼承是一種在已有類的基礎上去創建新類的方式。新建的類就叫做子類、或者派生類、衍生類,原始類就叫做父類、超類、基類。子類將繼承父類提供的方法和屬性,在此基礎上子類可以定義自己特有的方法和屬性。通過繼承也可以增強代碼複用,提高效率。


多態

子類通過重寫父類的方法,表現出不同的形態。例如貓和狗都繼承動物類,擁有動物類的makeVoice方法,但表現出了不同的叫聲,這就是多態的體現。


分享到:


相關文章: