其實(shí) Lua 中的 table 是一種對象,因?yàn)樗鷮ο笠粯?,有其自己的操作方法?/p>
上面代碼創(chuàng)建了一個(gè)名為 Role 對象,并有一個(gè) addHp 的方法,執(zhí)行 "Role.addHp" 便可調(diào)用 addHp 方法。
不過上面對象 Role 是以全局變量的方式創(chuàng)建,會有一種“全局污染”的威脅,即變量 Role 在其他地方被重新賦值(例如被賦成 nil),對象里的屬性或方法可能會面臨被銷毀或不能正常工作的情況。
對于這種問題,Lua 提供一種“接受者”的解決方法,即額外添加一個(gè)參數(shù) self 來表示對象本身:
這樣就不怕對象 Role 被“全局污染”,因?yàn)闃?gòu)造了一個(gè)子對象 r,并以參數(shù)的方式傳入,以供其方法調(diào)用操作。
對于這種把對象本身以參數(shù)的方式傳入對象方法里的寫法,Lua 提供了一種更優(yōu)雅的寫法,把點(diǎn)號(.)替換為冒號(:),這樣在方法定義或調(diào)用時(shí),便可隱藏 self 參數(shù)。修改如下:
上面的 "r.addHp(50)" 的寫法等價(jià)于 "r.addHp(r, 50)"
類
Lua 沒有類的概念,不過可以通過元表(metatable)來實(shí)現(xiàn)與原型 prototype 類似的功能,而 prototype 與類的工作機(jī)制一樣,都是定義了特定對象行為。Lua 里的原型特性主要使用元表的 __index 事件來實(shí)現(xiàn),這樣當(dāng)調(diào)用對象沒定義的方法時(shí),會向其元表的 __index 鍵(事件)查找。例如有 a 和 b 兩個(gè)對象,想讓 b 作為 a 的原型 prototype,只需要把 b 設(shè)置為 a 元表的 __index 值就行:
對于上面 Role 的例子,對象的創(chuàng)建可以用 __index 元方法來改寫,這樣新創(chuàng)建的對象就擁有和 Role 一樣的屬性和方法。
當(dāng)執(zhí)行 "r = Role:new() " 創(chuàng)建一個(gè)對象時(shí),r 將 Role 設(shè)置為自己的元表,那么調(diào)用 "r:addHp(50)" 的時(shí)候,會在 r 里查找 addHp 方法,如果沒有找到,則會進(jìn)一步搜索其元表的 __index,因此等價(jià)于:
從上面的 Role:new 方法可以知道,Role 的 __index 在創(chuàng)建時(shí)被指定為 self,因此其實(shí)就是執(zhí)行:
完整的類例子:
繼承
Lua 里繼承機(jī)制還是像實(shí)現(xiàn)類那樣實(shí)現(xiàn)。
假如打算從類 Role 派生出一個(gè)子類 Priest,它有一個(gè)魔法屬性值 mp,那么可以先從類 Role 構(gòu)造一個(gè) Priest,繼承類 Role 的所有屬性和方法:
雖然 Priest 是 Role 的一個(gè)實(shí)例,不過它具有類 Role 的所有屬性和方法,其實(shí)也可以把它看做是從類 Role 派生出來的類,因此可以從類 Priest 繼續(xù) new 一個(gè)對象出來:
上面實(shí)例 p 除了多出一個(gè)魔法屬性值 mp 外,還繼承類 Role 的所有屬性和方法,當(dāng)調(diào)用 "p.addHp" 方法時(shí),Lua 在 p 中找不到 addHp 方法,會到 Priest 中找,在 Priest 中找不到,會到 Role 中找。
因此,想重定義從父類 Role 繼承來的方法,在類 Priest 上定義即可。假如想重定義 addHp 方法:每次加血都要先判斷魔法值夠不夠,如果夠,則加血,并扣除一定的魔法值。修改如下:
標(biāo)簽:天門 宣城 濰坊 儋州 德宏 天門 臺灣 金昌
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Lua面向?qū)ο缶幊虒W(xué)習(xí)筆記》,本文關(guān)鍵詞 Lua,面向,對象,編程,學(xué)習(xí),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。