猴子原創,歡迎轉載。轉載請註明: 轉載自Cocos2D開發網–Cocos2Dev.com,謝謝!
原文地址: http://www.cocos2dev.com/?p=425
上次有個同學問我,說lua太簡單了,沒有什麼結構,也不好做物件導向編程。其實可以這樣說,Lua中的table就是一個對象。
下面我一點一點介紹Lua的物件導向編程。
一、對象的方法函數:
Hero = {attack = 100} function Hero.skill(addAttack) Hero.attack = Hero.attack + addAttack end Hero.skill(20) print(Hero.attack)--> 120
上面的先建立了一個函數,並調用該函數。
仔細的同學可能發現了,調用函數的時候使用了全域Hero。我在上一篇細節介紹中提過,Lua盡量減少全域變數的使用。而且這裡也有風險,一不小心修改了Hero,可能Hero就不能正常工作了。
那麼聯想到上一篇寫到的local temA = A,有人可能想到了這樣修改上面的函數調用:
oneHero = Hero; Hero = nil oneHero.skill(30) print(oneHero.attack) --> 錯誤,oneHero為nil
這樣也是錯誤的。因為Hero已經為nil了。
正確的如何修改呢?我們可以使用this/self 來實現:
Hero = {attack = 100} function Hero.skill(self,addAttack) self.attack = self.attack + addAttack end oneHero = Hero; Hero = nil oneHero.skill(oneHero,30) print(oneHero.attack) --> 130
OK,這下可以了,但是self每次需要自己傳,看著就麻煩,其實Lua也可以隱性調用self,我們在修改下:
Hero = {attack = 100} function Hero:skill(addAttack) self.attack = self.attack + addAttack end oneHero = Hero; Hero = nil oneHero:skill(30) print(oneHero.attack) --> 130
請注意上面 : 的使用,冒號可以在方法中添加一個額外的隱藏參數。上面其實也看到了Hero.skill() 和Hero:skill()的區別。
二、類,將table作為自己的元表
例如上面的Hero例子,我們修改下:
Hero = {} function Hero:new(o) o = o or {} setmetatable(o,self) self.__index = self return o end function Hero:skill(addAttack) self.attack = self.attack + addAttack end oneHero = Hero:new{attack = 90} oneHero:skill(10) print(oneHero.attack) -->100
建立一個新英雄的時候,oneHero將Hero設定為自己的元表,當oneHero:skill(10)的時候,在table oneHero中尋找skill,沒有找到後,會進一步搜尋元表的__index。
所以等價於:getmetatable(oneHero).__index.skill(oneHero,10)
而getmetatable(oneHero) 是Hero,Hero.__index還是Hero
所以等價於Hero.skill(oneHero,10)
三、繼承
例如:
Hero = {attack = 0} function Hero:new(o) o = o or {} setmetatable(o,self) self.__index = self return o end function Hero:skill(addAttack) self.attack = self.attack + addAttack end function Hero:injured(loseAttack) if loseAttack > self.attack then error"not engouth attack" end self.attack = self.attack - loseAttack end HumanHero = Hero:new() oneHero = HumanHero:new{attack = 100} oneHero:skill(10) print(oneHero.attack) -->110
每個對象沒有的方法都會去父類中尋找(這裡理解為父類),所以如果某個對象需要一些新的屬性方法,只需要在該對象中實現就可以了。