Python物件導向知多少?

尾生7發表於2019-06-06

問題場景

小王是某遊戲公司的新入職的職員,有一天,組長交給了他一個任務,為一個即將準開發的一款遊戲設計一些人物角色,其中包括多種職業,如牧師、戰士和法師等等。每種職業都有一些自身獨有的屬性和技能,但是也會有一些共有的屬性和方法。假設這家公司是用 Python 來開發遊戲的。

經歷過物件導向程式設計學習的小王很快就理清了思路,這需要用類的思想來進行設計。由於這些職業都會有一些共有的屬性和方法,顯然應該把這些職業的共有屬性和方法拿出來作為一個公共的類,而這個公共的類就叫做基類,或者稱為父類;其它職業可以基於這個公共的類來進行增加屬性和方法,這些職業的類就叫做子類。這就是物件導向編碼中的繼承的思想,理清了設計思路之後,小王立馬開始動手來實現相應的程式碼。


父類設計

首先,對於每一個遊戲角色,它都會有姓名和性別屬性。組長又告訴小王,我們不能讓其它人知道我們的角色是怎麼設計的,以及都有哪些屬性,這又該如何設計呢?聰明的小王立馬就想到了封裝的思想,通過隱藏物件的屬性和實現細節可以防止外部的類直接呼叫屬性或者修改屬性。所以小王立馬寫出瞭如下的程式碼:

class Roler(object):
    """
    使用者角色類,需要隱藏屬性
    Args:
        __username: 使用者名稱,string
        __sex:性別, string
    """
    def __init__(self, name=None, sex="male"):
        self.__username = name
        self.__sex = sex
        self.__hp = 1000

    def get_username(self):
        # 獲取使用者名稱
        return self.__username

    def get_sex(self):
        # 獲取使用者性別
        return self.__sex

    def add_hp(self, hpr):
        # 角色可以回血
        self.__hp += hpr

    def __repr__(self):
        # 列印物件資訊
        return "username : {0}\nsex : {1}\nhp : {2}".format(self.__username, self.__sex, self.__hp)

不同於 JavaC++ ,在 Python 中是沒有 private 等關鍵字的。所以我們如何來定義一個類的屬性是私有的呢?方法就是在類屬性的名字前加上兩個下劃線,即表示成 __username 的形式,這就是私有屬性的定義方式了。其原因是因為 Python 的類的內部,所有雙下劃線的開始的名字都會被替換成增加單下劃線和類名的方式。實質上,__username 就被替換成了 _Roler__username 的形式了。

role1 = Roler("weisheng", "male") # 建立一個新角色
print(role1) # 列印該角色的資訊,呼叫 __repr__() 方法

print(role1.__username) # AttributeError,該屬性是私有的
print(role1._Roler__username) # weisheng,可以列印

子類設計

有了父類還不夠,由於每個職業都會有一些自身特有的屬性和方法。所以,對於每個職業,我們也需要實現一個類。小王首先針對牧師這個職業來實現,牧師作為一個法系醫療職業,首先肯定需要一個 MP 值。同時,它能給其它使用者恢復生命值。因此,可以按照如下方式來實現牧師類:

class Pastor(Roler):
    """
    牧師類,繼承自使用者角色類
    Args:
        __MP: 魔法值
    """
    def __init__(self, name, sex):
        # 呼叫父類的建構函式
        super().__init__(name, sex)
        self.__mp = 100
    def get_mp(self):
        return self.__mp
    def __repr__(self):
        return super().__repr__() + "\nmp : {0}".format(self.__mp)

    def fullhealth(self, other):
        # 技能1:回覆其它使用者生命值
        other.add_hp(200)

在定義的牧師類中,首先呼叫父類的建構函式來對使用者姓名、性別、hp值進行初始化。同時,牧師還有個mp值,這個屬性是該職業獨有的(請勿追究細節)。由於增加了相應的屬性,所以 __repr__() 方法也需要重寫,可以通過呼叫父類的 __repr__() 方法再加上牧師類獨有的屬性。

子類不能直接呼叫父類的私有屬性,所以針對父類的一些私有屬性,需要通過方法來呼叫。

牧師還有一個技能,他能給其它的使用者角色回血,所以需要實習一個 fullhealth() 方法,引數是其它的角色類。測試用例如下:

pastor1 = Pastor("ergouzi", "male") # 建立一個牧師職業
print(pastor1)  # 列印該職業角色的資訊

pastor1.fullhealth(role1)  # 牧師可以給其他角色回血
print(role1)  # 可以發現該使用者的 hp 值發生變化

其他職業的設計可以參照該職業的特點來做出相應的設計,這裡就不在多做說明了。


物件導向總結

通過跟隨小王的遊戲角色設計,相信你已經對 Python 中的物件導向程式設計有了一定的瞭解了。物件導向程式設計是現在常用的一種程式設計方式,它是相對於程式導向程式設計來說的。物件導向程式設計把物件作為程式的基本單元,一個物件包含了資料和運算元據的函式。該思想最主要的三個特點就是封裝、繼承和多型,其實這些特點在上述的例項中都有體現,你能發現嗎?

雖然上述的例子已經闡述了物件導向程式設計的大部分思想,但是本人也是第一次去進行這些類間關係的設計,所以每個例子都是非常簡單的,可能在思想設計上也存在問題,請見諒。

全部程式碼請訪問:物件導向程式設計

更多精彩內容將釋出在公眾號 冰咖啡與狗 ,或搜尋微訊號 icedcoffee7 新增公眾號。

Python物件導向知多少?

相關文章