校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > Lua教程(十二):面向對象編程

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

熱門標簽:地圖標注大廈 怎么去除地圖標注 武漢外呼防封系統多少錢 百度地圖標注早餐區域 漳州智云呼電話機器人 冀州市地圖標注 新岸線智能電銷機器人 清朝地圖標注哈爾濱 個人怎么在地圖標注需要的店鋪

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表中。

您可能感興趣的文章:
  • Lua教程(一):簡介、優勢和應用場景介紹
  • Lua教程(二):基礎知識、類型與值介紹
  • Lua教程(三):表達式和語句
  • Lua教程(四):函數詳解
  • Lua教程(五):迭代器和泛型for
  • Lua教程(六):編譯執行與錯誤
  • Lua教程(七):數據結構詳解
  • Lua教程(八):數據持久化
  • Lua教程(九):元表與元方法詳解
  • Lua教程(十): 全局變量和非全局的環境
  • Lua教程(十一):模塊與包詳解

標簽:臺灣 儋州 天門 天門 濰坊 德宏 宣城 金昌

巨人網絡通訊聲明:本文標題《Lua教程(十二):面向對象編程》,本文關鍵詞  Lua,教程,十二,面向,對象,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Lua教程(十二):面向對象編程》相關的同類信息!
  • 本頁收集關于Lua教程(十二):面向對象編程的相關信息資訊供網民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    日韩va欧美va亚洲va久久| 国产乱对白刺激视频不卡 | 亚洲一卡二卡三卡四卡无卡久久| 国产色产综合色产在线视频| 日韩精品一区在线| 国产精品福利在线播放| 亚洲另类在线一区| 午夜久久久久久久久| 国产一区二区三区美女| 97久久精品人人做人人爽50路| 国产91精品久久久久久久网曝门| 色综合中文综合网| 欧美久久久久中文字幕| 欧美一区二区三区影视| 欧美成人精精品一区二区频| 亚洲国产精品一区二区尤物区| 看电视剧不卡顿的网站| 不卡视频一二三| 精品国产伦一区二区三区免费 | 欧美三级日韩在线| 久久婷婷成人综合色| 国产精品国产三级国产普通话99 | 国产色爱av资源综合区| 日本成人在线网站| 欧洲激情一区二区| 亚洲天堂av一区| 激情综合网av| 国产精品久久毛片a| 成人一区二区三区在线观看 | 亚洲国产毛片aaaaa无费看| www.欧美.com| 中文成人av在线| 一本色道久久综合狠狠躁的推荐| 国产午夜精品理论片a级大结局| 美女一区二区在线观看| 久久免费国产精品| 国产永久精品大片wwwapp| 日韩一级高清毛片| 韩国毛片一区二区三区| 精品精品欲导航| 激情另类小说区图片区视频区| 日韩午夜三级在线| 国产成人精品综合在线观看| 国产夜色精品一区二区av| 一个色综合网站| 亚洲精品在线观| 一本大道久久a久久精二百| 五月天精品一区二区三区| 日韩精品一区二区三区视频| 久久精品国产色蜜蜜麻豆| 国产欧美日韩另类一区| 欧亚洲嫩模精品一区三区| 麻豆精品一区二区av白丝在线| 欧美一区二区三区小说| 在线视频观看一区| 不卡电影免费在线播放一区| 久久国产精品99久久久久久老狼| 日韩精品一区二区在线| 欧美日韩不卡一区| 色婷婷av一区二区三区之一色屋| 麻豆精品一区二区综合av| 一区二区在线观看免费| 亚洲精品国产成人久久av盗摄| 久久综合色播五月| 精品国产自在久精品国产| 91精品国产综合久久婷婷香蕉| 欧美色图一区二区三区| 色婷婷亚洲一区二区三区| 国产精品伊人色| 风间由美性色一区二区三区| 国产mv日韩mv欧美| 国产九色sp调教91| 国产a视频精品免费观看| 国产一区二区三区四区五区美女| 奇米精品一区二区三区在线观看| 亚洲成在人线免费| 天天影视色香欲综合网老头| 亚洲国产你懂的| 久久精品二区亚洲w码| 经典三级视频一区| 国产在线精品一区在线观看麻豆| 热久久久久久久| 色网站国产精品| 日韩精品中文字幕一区二区三区 | 欧美不卡一区二区三区四区| 91麻豆精品国产91久久久久| 久久久久高清精品| 玉米视频成人免费看| 日韩电影在线观看电影| 成人avav影音| 欧美精品黑人性xxxx| 久久精品在线免费观看| 五月婷婷另类国产| 99精品视频在线免费观看| 91精品欧美久久久久久动漫| 中文一区在线播放| 国产一区二区导航在线播放| av中文字幕不卡| 26uuu久久综合| 亚洲成人免费观看| www.亚洲在线| 亚洲三级小视频| 欧美日韩一区国产| 午夜成人免费电影| 7777精品伊人久久久大香线蕉完整版| 国产三级精品三级| 极品销魂美女一区二区三区| 欧美精品久久99久久在免费线| 亚洲色大成网站www久久九九| 国产剧情av麻豆香蕉精品| 日韩欧美高清dvd碟片| 婷婷亚洲久悠悠色悠在线播放| 国产精品123| 国产亚洲成年网址在线观看| 捆绑调教美女网站视频一区| 精品国产露脸精彩对白| 国产一区在线精品| 亚洲欧美一区二区不卡| 色老头久久综合| 国产精品一二一区| 亚洲综合在线第一页| 欧美一级二级三级蜜桃| 久久精品国产99国产| 久久久精品tv| 欧美乱妇20p| 成人av在线一区二区三区| 偷窥国产亚洲免费视频| 欧美国产日韩在线观看| 欧美精选午夜久久久乱码6080| 国产一区二区伦理片| 亚洲国产aⅴ天堂久久| 国产日韩精品一区二区三区在线| 成人免费黄色在线| 久久精品99国产精品日本| 中文字幕免费不卡| 日韩一区二区在线看| 在线观看91精品国产入口| 国内精品国产成人国产三级粉色 | 成人免费不卡视频| 国内精品在线播放| 国产一区二区免费看| 午夜婷婷国产麻豆精品| 亚洲女同ⅹxx女同tv| 中文无字幕一区二区三区| 欧美大白屁股肥臀xxxxxx| 欧美日韩小视频| 欧美日韩一区二区不卡| 91黄视频在线观看| 欧美午夜视频网站| 日韩色视频在线观看| 欧美刺激午夜性久久久久久久| 欧美zozozo| 精品国产免费人成电影在线观看四季 | 91网页版在线| 色94色欧美sute亚洲线路一久| 一本到一区二区三区| 99久久久久久| 91九色02白丝porn| 日韩久久久精品| 国产精品你懂的在线欣赏| 亚洲色图.com| 美女视频免费一区| 97久久人人超碰| 精品日产卡一卡二卡麻豆| 亚洲欧美韩国综合色| 国内精品国产成人| 91麻豆精品国产91久久久使用方法| 国产精品麻豆网站| 激情偷乱视频一区二区三区| 日本精品一区二区三区高清 | 亚洲一区二区欧美日韩| 青青草国产精品97视觉盛宴| 在线播放日韩导航| 精久久久久久久久久久| 日韩免费观看高清完整版| 国产色一区二区| 国产成人日日夜夜| 久久久久久久久久美女| 久久精品国产精品亚洲红杏| 日韩一区二区视频在线观看| 亚洲第一二三四区| 91影院在线免费观看| 日韩一区和二区| 麻豆精品一区二区综合av| 日韩亚洲国产中文字幕欧美| 日韩国产高清影视| 欧美日韩电影在线| 蜜桃视频在线观看一区| 精品国产91久久久久久久妲己| 国产精品资源网| 国产精品国产自产拍在线| 91福利在线导航| 精品在线你懂的| 精品免费日韩av| 91美女精品福利| 日韩电影免费一区| 国产精品九色蝌蚪自拍| 制服丝袜亚洲精品中文字幕| 精品在线亚洲视频| 天堂午夜影视日韩欧美一区二区|