亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

Lua教程(十二):面向對象編程

2024-07-21 23:04:45
字體:
來源:轉載
供稿:網友

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

復制代碼 代碼如下:

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

 

在上面的withdraw函數內部依賴了全局變量Account,一旦該變量發生改變,將會導致withdraw不再能正常的工作,如:

復制代碼 代碼如下:

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

    這種行為明顯的違反了面向對象封裝性和實例獨立性。要解決這一問題,我們需要給withdraw函數在添加一個參數self,他等價于Java/C++中的this,見如下修改:
復制代碼 代碼如下:

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

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

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

 

1. 類:

Lua在語言上并沒有提供面向對象的支持,因此想實現該功能,我們只能通過table來模擬,見如下代碼及關鍵性注釋:

復制代碼 代碼如下:

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

 

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

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

--下面的代碼創建兩個Account的對象實例

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

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

 

2. 繼承:

繼承也是面向對象中一個非常重要的概念,在Lua中我們仍然可以像模擬類那樣來進一步實現面向對象中的繼承機制,見如下代碼及關鍵性注釋:

 

復制代碼 代碼如下:

--需要說明的是,這段代碼僅提供和繼承相關的注釋,和類相關的注釋在上面的代碼中已經給出。
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

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

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

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

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


--此時的withdraw方法將不再是Account中的withdraw方法,而是SpecialAccount中的該方法。
--這是因為Lua先在SpecialAccount(即s的元表)中找到了該方法。
s:withdraw(200.00)
print(s.balance) --輸出-100

 

3. 私密性:

私密性對于面向對象語言來說是不可或缺的,否則將直接破壞對象的封裝性。Lua作為一種面向過程的腳本語言,更是沒有提供這樣的功能,然而和模擬支持類與繼承一樣,我們仍然可以在Lua中通過特殊的編程技巧來實現它,這里我們應用的是Lua中的閉包函數。該實現方式和前面兩個示例中基于元表的方式有著很大的區別,見如下代碼示例和關鍵性注釋:

復制代碼 代碼如下:

--這里我們需要一個閉包函數作為類的創建工廠
function newAccount(initialBalance)
    --這里的self僅僅是一個普通的局部變量,其含義完全不同于前面示例中的self。
    --這里之所以使用self作為局部變量名,也是為了方便今后的移植。比如,以后
    --如果改為上面的實現方式,這里應用了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
    --返回對象中包含的字段僅僅為公有方法。事實上,我們通過該種方式,不僅可以實現
    --成員變量的私有性,也可以實現方法的私有性,如:
    --local privateFunction = function() --do something end
    --只要我們不在輸出對象中包含該方法的字段即可。
    return {withdraw = withdraw, deposit = deposit, getBalance = getBalance}
end

 

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

 

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品久久久一区| 日本精品久久久久久久| 伊人成人开心激情综合网| 欧美日韩国产一中文字不卡| 午夜精品久久久久久久99热浪潮| 91av视频在线播放| 欧美日韩亚洲高清| 日本老师69xxx| 日韩成人av一区| 日韩中文视频免费在线观看| 91免费人成网站在线观看18| 成人福利网站在线观看11| 亚洲精品乱码久久久久久按摩观| 亚洲欧美成人在线| 国产精品久久婷婷六月丁香| 亚洲午夜色婷婷在线| 欧美诱惑福利视频| 久久天堂av综合合色| 欧美又大粗又爽又黄大片视频| 欧美黑人性生活视频| 欧美日韩在线视频首页| 亚洲国产精品福利| 亚洲成人亚洲激情| 久久久99免费视频| 岛国av一区二区三区| 亚洲综合第一页| 亚洲欧美日韩精品久久亚洲区| 日韩在线资源网| 欧美另类精品xxxx孕妇| 久久久影视精品| 91欧美精品午夜性色福利在线| 亚洲第一视频网站| 这里只有精品在线播放| 亚洲 日韩 国产第一| 色哟哟网站入口亚洲精品| 琪琪亚洲精品午夜在线| 不卡av电影在线观看| 亚洲毛茸茸少妇高潮呻吟| 亚洲成人精品av| 最好看的2019年中文视频| 亚洲一区二区久久久| 日本亚洲精品在线观看| 国产性猛交xxxx免费看久久| 色久欧美在线视频观看| 国产综合福利在线| 91精品国产91久久久| 日韩av一区在线观看| 国产视频久久久久久久| 欧美精品videossex88| 亚洲欧洲国产一区| 中文字幕精品视频| 欧美另类老肥妇| 国产精品久久久久久久一区探花| 国产99久久精品一区二区永久免费| 成人黄色片在线| 国产午夜精品理论片a级探花| 国模视频一区二区| 亚洲欧美日韩精品| 欧美日韩性生活视频| 国模叶桐国产精品一区| 精品久久久在线观看| 欧美午夜视频一区二区| 韩曰欧美视频免费观看| 亚洲老司机av| 欧美一区二区视频97| 亚洲乱码av中文一区二区| 国产一区二区三区毛片| 一夜七次郎国产精品亚洲| 成人免费直播live| 伊人激情综合网| 欧美日韩福利在线观看| 亚洲精品中文字幕女同| 色偷偷av一区二区三区乱| 成人在线激情视频| 超碰97人人做人人爱少妇| 国产精品自在线| 91wwwcom在线观看| 98精品在线视频| 久热在线中文字幕色999舞| 久久久久五月天| 亚洲免费电影在线观看| 欧美专区日韩视频| 欧美床上激情在线观看| 琪琪亚洲精品午夜在线| 欧洲成人午夜免费大片| 欧美日韩国产一区在线| 国产激情久久久| 91探花福利精品国产自产在线| 精品偷拍一区二区三区在线看| 欧美综合第一页| 日韩精品在线视频| 国内精品久久久久久影视8| 岛国av一区二区在线在线观看| 在线成人免费网站| 91成品人片a无限观看| 午夜精品一区二区三区在线视频| 日韩欧美在线观看视频| 亚洲精品久久久久久久久久久| 国产在线播放91| 亚洲精美色品网站| 中文字幕日韩精品在线| 欧美在线不卡区| 97涩涩爰在线观看亚洲| 久久免费少妇高潮久久精品99| 国产一区视频在线播放| 欧美色道久久88综合亚洲精品| 亚洲精品98久久久久久中文字幕| 国产一区二区三区久久精品| 国产丝袜一区二区三区| 精品爽片免费看久久| 精品久久久久久久久久久久久| 欧美成人激情视频免费观看| 久久91亚洲精品中文字幕奶水| 亚洲自拍偷拍在线| 久久国产精品久久久久久| 91美女片黄在线观| 欧美日韩国产第一页| 大桥未久av一区二区三区| 亚洲国产91精品在线观看| 国产婷婷色综合av蜜臀av| 欧美激情精品久久久久久免费印度| 日韩一区二区三区xxxx| 欧美日韩精品在线观看| 亚洲丁香婷深爱综合| 亚洲综合国产精品| 亚洲福利视频专区| 在线性视频日韩欧美| 成人中文字幕+乱码+中文字幕| 亚洲天堂av女优| 黑丝美女久久久| 亚洲国产免费av| 欧美精品成人在线| 精品亚洲一区二区三区在线观看| 国产精品视频自在线| 亚洲国产精品福利| 91麻豆桃色免费看| 国内精久久久久久久久久人| 欧美在线视频导航| 亚洲人成欧美中文字幕| 中国日韩欧美久久久久久久久| 欧美激情一区二区三级高清视频| 亚洲色图av在线| 久久亚洲综合国产精品99麻豆精品福利| 在线看国产精品| 国产精品入口日韩视频大尺度| 日韩女优在线播放| 7777精品久久久久久| 欧美另类极品videosbestfree| 日韩精品日韩在线观看| 国产精品久久久久久久久久久久久久| 欧美性在线观看| 国产噜噜噜噜久久久久久久久| 精品美女久久久久久免费| 亚洲国产小视频| 国产精品视频大全| 亚洲第一视频网站| 亚洲免费小视频| 欧美激情在线狂野欧美精品| 亚洲色图偷窥自拍| 色视频www在线播放国产成人| 成人免费看黄网站| 欧美亚洲一区在线| 亚洲日本中文字幕| 欧美极度另类性三渗透|