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

在這裏插入圖片描述

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

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)

封裝

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

繼承

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

多態

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章