最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Lua教程(十二):面向?qū)ο缶幊?/h1>
 更新時(shí)間:2015年04月30日 09:04:50   投稿:junjie  
這篇文章主要介紹了Lua教程(十二):面向?qū)ο缶幊?本文講解了類、繼承、私密性等面向?qū)ο缶幊讨R,需要的朋友可以參考下

Lua中的table就是一種對象,但是如果直接使用仍然會存在大量的問題,見如下代碼:

復(fù)制代碼 代碼如下:

 Account = {balance = 0}
 function Account.withdraw(v)
     Account.balance = Account.balance - v
 end
 --下面是測試調(diào)用函數(shù)
 Account.withdraw(100.00)

在上面的withdraw函數(shù)內(nèi)部依賴了全局變量Account,一旦該變量發(fā)生改變,將會導(dǎo)致withdraw不再能正常的工作,如:

復(fù)制代碼 代碼如下:

 a = Account; Account = nil
 a.withdraw(100.00)  --將會導(dǎo)致訪問空nil的錯(cuò)誤。

    這種行為明顯的違反了面向?qū)ο蠓庋b性和實(shí)例獨(dú)立性。要解決這一問題,我們需要給withdraw函數(shù)在添加一個(gè)參數(shù)self,他等價(jià)于Java/C++中的this,見如下修改:
復(fù)制代碼 代碼如下:

 function Account.withdraw(self,v)
     self.balance = self.balance - v
 end
 --下面是基于修改后代碼的調(diào)用:
 a1 = Account; Account = nil
 a1.withdraw(a1,100.00)  --正常工作。

    針對上述問題,Lua提供了一種更為便利的語法,即將點(diǎn)(.)替換為冒號(:),這樣可以在定義和調(diào)用時(shí)均隱藏self參數(shù),如:
復(fù)制代碼 代碼如下:

 function Account:withdraw(v)
     self.balance = self.balance - v
 end
 --調(diào)用代碼可改為:
 a:withdraw(100.00)

1. 類:

Lua在語言上并沒有提供面向?qū)ο蟮闹С?,因此想?shí)現(xiàn)該功能,我們只能通過table來模擬,見如下代碼及關(guān)鍵性注釋:

復(fù)制代碼 代碼如下:

--[[
在這段代碼中,我們可以將Account視為class的聲明,如Java中的:
public class Account
{
    public float balance = 0;
    public Account(Account o);
    public void deposite(float f);
}
--]]
--這里balance是一個(gè)公有的成員變量。
Account = {balance = 0}

--new可以視為構(gòu)造函數(shù)
function Account:new(o)
    o = o or {} --如果參數(shù)中沒有提供table,則創(chuàng)建一個(gè)空的。
    --將新對象實(shí)例的metatable指向Account表(類),這樣就可以將其視為模板了。
    setmetatable(o,self)
    --在將Account的__index字段指向自己,以便新對象在訪問Account的函數(shù)和字段時(shí),可被直接重定向。
    self.__index = self
    --最后返回構(gòu)造后的對象實(shí)例
    return o
end

--deposite被視為Account類的公有成員函數(shù)
function Account:deposit(v)
    --這里的self表示對象實(shí)例本身
    self.balance = self.balance + v
end

--下面的代碼創(chuàng)建兩個(gè)Account的對象實(shí)例

--通過Account的new方法構(gòu)造基于該類的示例對象。
a = Account:new()
--[[
這里需要具體解釋一下,此時(shí)由于table a中并沒有deposite字段,因此需要重定向到Account,
同時(shí)調(diào)用Account的deposite方法。在Account.deposite方法中,由于self(a對象)并沒有balance
字段,因此在執(zhí)行self.balance + v時(shí),也需要重定向訪問Account中的balance字段,其缺省值為0。
在得到計(jì)算結(jié)果后,再將該結(jié)果直接賦值給a.balance。此后a對象就擁有了自己的balance字段和值。
下次再調(diào)用該方法,balance字段的值將完全來自于a對象,而無需在重定向到Account了。
--]]
a:deposit(100.00)
print(a.balance) --輸出100

b = Account:new()
b:deposit(200.00)
print(b.balance) --輸出200

2. 繼承:

繼承也是面向?qū)ο笾幸粋€(gè)非常重要的概念,在Lua中我們?nèi)匀豢梢韵衲M類那樣來進(jìn)一步實(shí)現(xiàn)面向?qū)ο笾械睦^承機(jī)制,見如下代碼及關(guān)鍵性注釋:

復(fù)制代碼 代碼如下:

--需要說明的是,這段代碼僅提供和繼承相關(guān)的注釋,和類相關(guān)的注釋在上面的代碼中已經(jīng)給出。
Account = {balance = 0}

function Account:new(o)
    o = o or {}
    setmetatable(o,self)
    self.__index = self
    return o
end

function Account:deposit(v)
    self.balance = self.balance + v
end

function Account:withdraw(v)
    if v > self.balance then
        error("Insufficient funds")
    end
    self.balance = self.balance - v
end

--下面將派生出一個(gè)Account的子類,以使客戶可以實(shí)現(xiàn)透支的功能。
SpecialAccount = Account:new()  --此時(shí)SpecialAccount仍然為Account的一個(gè)對象實(shí)例

--派生類SpecialAccount擴(kuò)展出的方法。
--下面這些SpecialAccount中的方法代碼(getLimit/withdraw),一定要位于SpecialAccount被Account構(gòu)造之后。
function SpecialAccount:getLimit()
    --此時(shí)的self將為對象實(shí)例。
    return self.limit or 0
end

--SpecialAccount將為Account的子類,下面的方法withdraw可以視為SpecialAccount
--重寫的Account中的withdraw方法,以實(shí)現(xiàn)自定義的功能。
function SpecialAccount:withdraw(v)
    --此時(shí)的self將為對象實(shí)例。
    if v - self.balance >= self:getLimit() then
        error("Insufficient funds")
    end
    self.balance = self.balance - v
end

--在執(zhí)行下面的new方法時(shí),table s的元表已經(jīng)是SpecialAccount了,而不再是Account。
s = SpecialAccount:new{limit = 1000.00}
--在調(diào)用下面的deposit方法時(shí),由于table s和SpecialAccount均未提供該方法,因此訪問的仍然是
--Account的deposit方法。
s:deposit(100)


--此時(shí)的withdraw方法將不再是Account中的withdraw方法,而是SpecialAccount中的該方法。
--這是因?yàn)長ua先在SpecialAccount(即s的元表)中找到了該方法。
s:withdraw(200.00)
print(s.balance) --輸出-100

3. 私密性:

私密性對于面向?qū)ο笳Z言來說是不可或缺的,否則將直接破壞對象的封裝性。Lua作為一種面向過程的腳本語言,更是沒有提供這樣的功能,然而和模擬支持類與繼承一樣,我們?nèi)匀豢梢栽贚ua中通過特殊的編程技巧來實(shí)現(xiàn)它,這里我們應(yīng)用的是Lua中的閉包函數(shù)。該實(shí)現(xiàn)方式和前面兩個(gè)示例中基于元表的方式有著很大的區(qū)別,見如下代碼示例和關(guān)鍵性注釋:

復(fù)制代碼 代碼如下:

--這里我們需要一個(gè)閉包函數(shù)作為類的創(chuàng)建工廠
function newAccount(initialBalance)
    --這里的self僅僅是一個(gè)普通的局部變量,其含義完全不同于前面示例中的self。
    --這里之所以使用self作為局部變量名,也是為了方便今后的移植。比如,以后
    --如果改為上面的實(shí)現(xiàn)方式,這里應(yīng)用了self就可以降低修改的工作量了。
    local self = {balance = initialBalance} --這里我們可以將self視為私有成員變量
    local withdraw = function(v) self.balance = self.balance - v end
    local deposit = function(v) self.balance = self.balance + v end
    local getBalance = function() return self.balance end
    --返回對象中包含的字段僅僅為公有方法。事實(shí)上,我們通過該種方式,不僅可以實(shí)現(xiàn)
    --成員變量的私有性,也可以實(shí)現(xiàn)方法的私有性,如:
    --local privateFunction = function() --do something end
    --只要我們不在輸出對象中包含該方法的字段即可。
    return {withdraw = withdraw, deposit = deposit, getBalance = getBalance}
end

--和前面兩個(gè)示例不同的是,在調(diào)用對象方法時(shí),不再需要self變量,因此我們可以直接使用點(diǎn)(.),
--而不再需要使用冒號(:)操作符了。
accl = newAccount(100.00)
--在函數(shù)newAccount返回之后,該函數(shù)內(nèi)的“非局部變量”表self就不再能被外部訪問了,只能通過
--該函數(shù)返回的對象的方法來操作它們。
accl.withdraw(40.00)
print(acc1.getBalance())

事實(shí)上,上面的代碼只是給出一個(gè)簡單的示例,在實(shí)際應(yīng)用中,我們可以將更多的私有變量存放于上例的局部self表中。

相關(guān)文章

  • Lua和C語言的交互詳解

    Lua和C語言的交互詳解

    這篇文章主要介紹了Lua和C語言的交互詳解,Lua和C語言通過棧完成交互,本文結(jié)合代碼實(shí)例詳細(xì)講解了交互的方法,需要的朋友可以參考下
    2014-09-09
  • Lua教程(十七):C API簡介

    Lua教程(十七):C API簡介

    這篇文章主要介紹了Lua教程(十七):C API簡介,本文講解了基礎(chǔ)知識、棧、C API中的錯(cuò)誤處理、Lua調(diào)用C程序、C程序調(diào)用Lua代碼的錯(cuò)誤處理等內(nèi)容,需要的朋友可以參考下
    2015-04-04
  • Lua讀寫文件代碼示例

    Lua讀寫文件代碼示例

    這篇文章主要介紹了Lua讀寫文件代碼示例,本文講解了讀寫文件的模式以及讀寫文件代碼實(shí)例,需要的朋友可以參考下
    2015-04-04
  • Lua中的for循環(huán)和迭代器的秘密探究

    Lua中的for循環(huán)和迭代器的秘密探究

    這篇文章主要介紹了Lua中的for循環(huán)和迭代器的秘密探究,本文講解了返回兩個(gè)值的迭代器、for .. in .. do的真面目、迭代器函數(shù)、恒定狀態(tài)、控制變量初值等內(nèi)容,需要的朋友可以參考下
    2014-09-09
  • Lua中的模塊與module函數(shù)詳解

    Lua中的模塊與module函數(shù)詳解

    這篇文章主要介紹了Lua中的模塊與module函數(shù)詳解,本文講解了編寫一個(gè)簡單的模塊、避免修改模塊名的方法、模塊名參數(shù)等內(nèi)容,需要的朋友可以參考下
    2014-09-09
  • 解析Lua中的全局環(huán)境、包、模塊組織結(jié)構(gòu)

    解析Lua中的全局環(huán)境、包、模塊組織結(jié)構(gòu)

    Lua中也擁有和Python世界相似的代碼的作用范圍和組織方式,下面我們就來簡單解析Lua中的全局環(huán)境、包、模塊組織結(jié)構(gòu),需要的朋友可以參考下
    2016-06-06
  • Lua中的元表(metatable)、元方法(metamethod)詳解

    Lua中的元表(metatable)、元方法(metamethod)詳解

    這篇文章主要介紹了Lua中的元表(metatable)、元方法(metamethod)詳解,本文對它做了詳細(xì)講解,并給出實(shí)例來說明,需要的朋友可以參考下
    2014-09-09
  • Lua教程(六):綁定一個(gè)簡單的C++類

    Lua教程(六):綁定一個(gè)簡單的C++類

    這篇文章主要介紹了Lua教程(六):綁定一個(gè)簡單的C++類,本文是最后一篇C/C++與Lua交互的教程,其他教程請參閱本文下方的相關(guān)文章,需要的朋友可以參考下
    2014-09-09
  • 舉例詳解Lua中的協(xié)同程序編程

    舉例詳解Lua中的協(xié)同程序編程

    這篇文章主要介紹了Lua中的協(xié)同程序編程,是Lua入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-05-05
  • Lua Table轉(zhuǎn)C# Dictionary的方法示例

    Lua Table轉(zhuǎn)C# Dictionary的方法示例

    這篇文章主要給大家介紹了關(guān)于Lua Table轉(zhuǎn)C# Dictionary的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03

最新評論

友谊县| 甘孜| 东方市| 西充县| 古蔺县| 漳平市| 盐池县| 广平县| 甘南县| 普宁市| 突泉县| 海门市| 鸡泽县| 广元市| 双鸭山市| 新蔡县| 溧水县| 金秀| 舞阳县| 保靖县| 孙吴县| 石河子市| 岗巴县| 花莲县| 宣威市| 突泉县| 通化县| 克山县| 蒲江县| 库尔勒市| 栾川县| 江北区| 神池县| 体育| 台东县| 承德县| 石林| 永新县| 南部县| 文成县| 岱山县|