Python 新手之旅 V1.10 - 單元 4 - Python 與物件導向程式設計





































Python 新手之旅 V1.10 - 單元 4 - Python 與物件導向程式設計








物件導向程式設計 (object-oriented programming) 是對真實世界的比擬,例如我們設計一個模擬租借腳踏車的系統,租腳踏車的是人,利用電子錢包扣款租借,因此「人」、「電子錢包」、「腳踏車」在這個系統中都會是獨立的物件 (object) 。



以下寫個簡單程式來模擬,如下




























































































































































































































001
class Person:
002    name = ""
003    wallet = None
004    bike = None
005 
006    def __init__(self, name):
007        self.name = name
008        m = "A person "
009        m += self.name
010        m += " is here."
011        print(m)
012 
013    def setWallet(self, wallet):
014        self.wallet = wallet
015        m = self.name
016        m += " has the new wallet."
017        print(m)
018 
019    def rentBike(self, bike):
020        self.wallet.balance -= 50
021        self.bike = bike
022        m = self.name
023        m += "'s wallet now has "
024        m += str(self.wallet.balance)
025        m += " dollars."
026        print(m)
027 
028
class ElectronWallet:
029    balance = 0
030    person = None
031 
032    def __init__(self, person, balance):
033        self.person = person
034        self.balance = balance
035        m = "A new wallet has "
036        m += str(self.balance)
037        m += " dollars."
038        print(m)
039 
040
class RenterBike:
041    person = None
042 
043    def __init__(self, person):
044        self.person = person
045        m = "A bike is rented by "
046        m += self.person.name
047        m += "."
048        print(m)
049 
050someone = Person("John")
051newWallet = ElectronWallet(someone, 1000)
052someone.setWallet(newWallet)
053newBike = RenterBike(someone)
054someone.rentBike(newBike)


「人」用類別 (class) Person 來模擬












































































































001
class Person:
002    name = ""
003    wallet = None
004    bike = None
005 
006    def __init__(self, name):
007        self.name = name
008        m = "A person "
009        m += self.name
010        m += " is here."
011        print(m)
012 
013    def setWallet(self, wallet):
014        self.wallet = wallet
015        m = self.name
016        m += " has the new wallet."
017        print(m)
018 
019    def rentBike(self, bike):
020        self.wallet.balance -= 50
021        self.bike = bike
022        m = self.name
023        m += "'s wallet now has "
024        m += str(self.wallet.balance)
025        m += " dollars."
026        print(m)


Person 的屬性 wallet 是對「電子錢包」的連結,因為「人」也可以沒有「電子錢包」,所以初值設定成 None ,等到「人」有了「電子錢包」之後,再用 setWallet() 設定「電子錢包」。



而屬性 bike 則是對「腳踏車」的連結,還沒有租借當然也沒有腳踏車,所以初值也是設定成 None ,實際租借則是使用 rentBike() 方法,此時會從「電子錢包」扣款,然後完成 bike 的設定。



由上看來,可以發現 Person 對「電子錢包」及「腳踏車」兩個物件都有著緊密的關係,至於「電子錢包」用 ElectronWallet 來模擬,如下
















































028
class ElectronWallet:
029    balance = 0
030    person = None
031 
032    def __init__(self, person, balance):
033        self.person = person
034        self.balance = balance
035        m = "A new wallet has "
036        m += str(self.balance)
037        m += " dollars."
038        print(m)


這是採記名制的「電子錢包」,因此每個 ElectronWallet 利用屬性 person 對應到專屬的 Person 物件,當然也不排除一個 Person 可以有多個 ElectronWallet



最後「腳踏車」用 RenterBike 來模擬,如下








































040
class RenterBike:
041    person = None
042 
043    def __init__(self, person):
044        self.person = person
045        m = "A bike is rented by "
046        m += self.person.name
047        m += "."
048        print(m)


RenterBike 同樣用屬性 person 保持對 Person 的連結,也默許一個 Person 可以租借多台 RenterBike



我們用以下程式碼模擬租借過程
























050someone = Person("John")
051newWallet = ElectronWallet(someone, 1000)
052someone.setWallet(newWallet)
053newBike = RenterBike(someone)
054someone.rentBike(newBike)


檔名儲存為 objectdemo.py ,執行結果如下











$ python3 objectdemo.py
A person John is here.
A new wallet has 1000 dollars.
John has the new wallet.
A bike is rented by John.
John's wallet now has 950 dollars.
$


以上說明物件導向程式設計著重在物件與物件的互動跟連結, Python 基本上就是按照物件導向的概念設計的程式語言,涵蓋物件導向的三大特性




  • 封裝 (encapsulation)

  • 繼承 (inheritance)

  • 多型 (polymorphism)



封裝的意思就是設定屬性的存取權限,一般而言, Python 中類別的屬性都是公開的,也就是建立物件後就能直接運用小數點存取屬性。



如果不想要某個類別中的屬性被任意存取,就需要將屬性封裝了。封裝是在屬性前加上兩條底線,例如












001
class EC:
002    __x = 0


這樣如果還想直接用小數點存取屬性 __x ,就會出現找不到的訊息







Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'EC' object has no attribute '__x'


繼承的意思則是取出物件系統中多個類別共通的屬性及方法,將共通的部分設計成父類別 (superclass) ,再設計不同的子類別 (subclass) 去實作不同的部分,同時讓子類別繼承自父類別,這樣讓每種子類別都能有共通的屬性及方法。



例如有以下的類別 SC
























001
class SC:
002    a = 11
003 
004    def do_something():
005        print("Hello, SC!")


繼承的寫法就是類別識別字後加上小括弧,然後小括弧中放父類別的名稱,例如以下的 SC2
























001
class SC2(SC):
002    b = 22
003 
004    def do_something():
005        print("Hello, SC2!")


這樣 SC2 除了有屬性 b 跟方法 do_something() 之外,也會有屬性 a ,至於原本 SCdo_something() 則被 SC2do_something() 改寫 (override) 了。



這個情況是說,子類別如果設置跟父類別相同名稱的屬性或方法,基本上會以子類別的版本為主,如果子類別想要使用已經改寫過的父類別內容,就得用 super 關鍵字來呼叫。



所以想得到繼承機制是怎麼運作的嗎? Python 直譯器會先建立父類別的物件,然後才去建立子類別的物件,當子類別物件需要用到父類別的屬性跟方法時,就會向父類別物件提出要求使用,基本上父類別跟子類別的物件都是同時存在的。



「繼承」這個詞是社群沿用已久的詞,所以這裡仍是把 inheritance 當「繼承」來講,實際上中文的「繼承」隱含某人已死的概念,可是物件導向中完全沒有這個意思。事實是 inherit 僅僅是某物得到某物的意思,所以生物學的「遺傳」也是用 inherit 這個詞。



至於多型的概念有很多,最狹義的不外是因為繼承關係,像是 BC 兩個類別繼承自 ABC 能夠使用 A 相同名稱的方法。好比設計一個動物遊戲, Animal 作為所有動物的父類別,另設計 DogCat 繼承 Animal 等動物類別,每種動物都可以使用 hello() 方法,只是每一種動物說 hello() 的方式都可以不一樣。



簡單講,進入 Python 世界就是物件的世界, Python 中所有的一切都是物件,就算是數字 12.2 也是物件,其他像字串 (string) 、串列 (list) 、字典 (dictionary) 等也當然都是物件的一種。



the end



Python 新手之旅 V1.10 (Google Play)

  • 單元 1 - Python 的資源

  • 單元 2 - Python 的開發工具

  • 單元 3 - Python 與數學

  • 單元 4 - Python 與物件導向程式設計

  • 單元 5 - Python 的測試、除錯與模組

  • 單元 6 - Python 中豐富的標準模組庫

  • 單元 7 - Python 有各式各類的開發應用

  • 單元 8 - Pyhton 的模組庫管理及編譯成執行檔








沒有留言:




















window.___gcfg = { 'lang': 'zh-TW' };





Popular posts from this blog

迅雷 Thunder 7.9.43.5054 免安裝版 (9.1.41.914 安裝版) - 支援BT下載的萬用 檔案下載工具

qBittorrent 4.1.1 免安裝中文版 - 取代uTorrent的BT下載器

Nhiều đồn đoán cho rằng bộ đồ "phá vỡ quy tắc" của Meghan Markle được lấy cảm hứng từ trang phục của Công nương Diana