類別

截至目前為止,我們使用 type() 函數觀察的資料或是容器,都是 Python 的內建類別,像是 strintlist 等,不同的這些類別可能包含不同的屬性(attributes)與方法(methods),像是一個文字有 upper()lower() 方法能夠改變大小寫:

my_name = "Tony"
print my_name.upper()
print my_name.lower()

圖 7-1 文字的方法

屬性與方法聽起來有點抽象,但實際上它們就是隸屬於某個類別的資料(data)與函數(function)。

7.1 自訂類別

7.1.1 屬性

除了使用內建的類別以外,Python 也容許我們自訂類別藉此建立擁有客製方法與屬性的物件。我們使用 class 語法來定義類別,並使用大寫開頭(Capitalized)單字為類別命名。現在讓我們來建立一個類別叫做 Building,建築物有一個屬性是名稱,就像在玩戰略遊戲一般,可以蓋城鎮中心、軍營或者修道院。

class Building():
    def __init__(self, name):
        self.name = name

town_center = Building("Town Center")
barrack = Building("Barrack")
monastery = Building("Monastery")

print town_center.name
print barrack.name
print monastery.name

圖 7-2 自訂類別屬性

如果對於 __init__ 方法與 self 參數感到困惑,就先記得這是 Python 的慣例,它用來幫助我們創造屬於這個類別的物件。

7.1.2 方法

建築物除了具有名稱這個屬性,還有一個基本方法是生產,比如城鎮中心能夠生產村民、軍營能夠生產戰士或者修道院能夠生產僧侶。

class Building():
    def __init__(self, name, unit):
        self.name = name
        self.unit = unit

    def create(self):
        return "%s 生產 %s" %(self.name, self.unit)

town_center = Building("Town Center", "Villager")
barrack = Building("Barrack", "Swordsman")
monastery = Building("Monastery", "Monk")

print town_center.create()
print barrack.create()
print monastery.create()

圖 7-3 自訂類別方法

7.2 繼承

戰略遊戲中的建築除了具備前述的基本屬性及方法,有時還會有其他進階的功能,比如具備庇護或者攻擊的能力。因此我們會需要自訂新的類別來滿足這些建築,但假如每次自訂新的類別就必須複製貼上建築的基本屬性及方法,不但很辛苦,未來也不容易維護,為了解決這樣的難題,類別具有繼承的特性,例如 Castle 類別可以繼承 Building

class Building():
    def __init__(self, name, unit):
        self.name = name
        self.unit = unit

    def create(self):
        return "%s 生產 %s" %(self.name, self.unit)

class Castle(Building):
    pass

castle = Castle("Castle", "Unique Unit")
print castle.name
print castle.create()

圖 7-4 繼承

因為在自訂 Castle 類別時繼承了 Building 類別(在小括號中輸入想要繼承的類別名稱),即便我們只有在 Castle 類別中輸入 pass,這個類別還是具備名稱屬性與生產方法。

7.2.1 新增或改寫方法

繼承了 Building 類別的 Castle 類別可以新增與改寫方法:

class Building():
    def __init__(self, name, unit):
        self.name = name
        self.unit = unit

    def create(self):
        return "%s 生產 %s" %(self.name, self.unit)

class Castle(Building):
    def create(self):
        return "%s 生產 %s 與 Trebuchet" %(self.name, self.unit)

    def attack(self):
        return "%s fires arrows!" %(self.name)

castle = Castle("Castle", "Unique Unit")
print castle.name
print castle.create()
print castle.attack()

圖 7-5 新增或改寫方法

7.2.2 新增屬性

在繼承時使用 super() 就可以建立新的屬性並保留原類別的屬性,例如我們可以在繼承 BuildingCastle 類別中新增一個 siege_unit 屬性:

class Building(object):
    def __init__(self, name, unit):
        self.name = name
        self.unit = unit

    def create(self):
        return "%s 生產 %s" %(self.name, self.unit)

class Castle(Building):
    def __init__(self, name, unit, siege_unit):
        super(Castle, self).__init__(name, unit)
        self.siege_unit = siege_unit

    def create(self):
        return "%s 生產 %s 與 %s" %(self.name, self.unit, self.siege_unit)

castle = Castle("Castle", "Unique Unit", "Trebuchet")
print castle.create()

圖 7-6 新增屬性

這裡的程式要特別注意我們讓 Building 類別先繼承 Python 的 object 類別,如此才能夠順利使用 super(),否則我們的 Building 會被歸類為舊式類別(old style class),在使用 super() 時會出現 TypeError: super() argument 1 must be type, not classobj 的錯誤訊息。

圖 7-7 錯誤訊息

results matching ""

    No results matching ""