問題場景
小王是某游戲公司的新入職的職員,有一天,組長交給了他一個任務,為一個即將准開發的一款游戲設計一些人物角色,其中包括多種職業,如牧師、戰士和法師等等。每種職業都有一些自身獨有的屬性和技能,但是也會有一些共有的屬性和方法。假設這家公司是用 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)
不同於 Java 和 C++ ,在 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 添加公眾號。

