• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            每天早晨叫醒你的不是鬧鐘,而是夢想

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              62 Posts :: 0 Stories :: 5 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(1)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

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

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

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

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

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

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

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

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


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

            復制代碼
             1 --[[
            2 在這段代碼中,我們可以將Account視為class的聲明,如Java中的:
            3 public class Account
            4 {
            5 public float balance = 0;
            6 public Account(Account o);
            7 public void deposite(float f);
            8 }
            9 --]]
            10 --這里balance是一個公有的成員變量。
            11 Account = {balance = 0}
            12
            13 --new可以視為構造函數
            14 function Account:new(o)
            15 o = o or {} --如果參數中沒有提供table,則創建一個空的。
            16 --將新對象實例的metatable指向Account表(類),這樣就可以將其視為模板了。
            17 setmetatable(o,self)
            18 --在將Account的__index字段指向自己,以便新對象在訪問Account的函數和字段時,可被直接重定向。
            19 self.__index = self
            20 --最后返回構造后的對象實例
            21 return o
            22 end
            23
            24 --deposite被視為Account類的公有成員函數
            25 function Account:deposit(v)
            26 --這里的self表示對象實例本身
            27 self.balance = self.balance + v
            28 end
            29
            30 --下面的代碼創建兩個Account的對象實例
            31
            32 --通過Account的new方法構造基于該類的示例對象。
            33 a = Account:new()
            34 --[[
            35 這里需要具體解釋一下,此時由于table a中并沒有deposite字段,因此需要重定向到Account,
            36 同時調用Account的deposite方法。在Account.deposite方法中,由于self(a對象)并沒有balance
            37 字段,因此在執行self.balance + v時,也需要重定向訪問Account中的balance字段,其缺省值為0。
            38 在得到計算結果后,再將該結果直接賦值給a.balance。此后a對象就擁有了自己的balance字段和值。
            39 下次再調用該方法,balance字段的值將完全來自于a對象,而無需在重定向到Account了。
            40 --]]
            41 a:deposit(100.00)
            42 print(a.balance) --輸出100
            43
            44 b = Account:new()
            45 b:deposit(200.00)
            46 print(b.balance) --輸出200
            復制代碼


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

            復制代碼
             1 --需要說明的是,這段代碼僅提供和繼承相關的注釋,和類相關的注釋在上面的代碼中已經給出。
            2 Account = {balance = 0}
            3
            4 function Account:new(o)
            5 o = o or {}
            6 setmetatable(o,self)
            7 self.__index = self
            8 return o
            9 end
            10
            11 function Account:deposit(v)
            12 self.balance = self.balance + v
            13 end
            14
            15 function Account:withdraw(v)
            16 if v > self.balance then
            17 error("Insufficient funds")
            18 end
            19 self.balance = self.balance - v
            20 end
            21
            22 --下面將派生出一個Account的子類,以使客戶可以實現透支的功能。
            23 SpecialAccount = Account:new() --此時SpecialAccount仍然為Account的一個對象實例
            24
            25 --派生類SpecialAccount擴展出的方法。
            26 --下面這些SpecialAccount中的方法代碼(getLimit/withdraw),一定要位于SpecialAccount被Account構造之后。
            27 function SpecialAccount:getLimit()
            28 --此時的self將為對象實例。
            29 return self.limit or 0
            30 end
            31
            32 --SpecialAccount將為Account的子類,下面的方法withdraw可以視為SpecialAccount
            33 --重寫的Account中的withdraw方法,以實現自定義的功能。
            34 function SpecialAccount:withdraw(v)
            35 --此時的self將為對象實例。
            36 if v - self.balance >= self:getLimit() then
            37 error("Insufficient funds")
            38 end
            39 self.balance = self.balance - v
            40 end
            41
            42 --在執行下面的new方法時,table s的元表已經是SpecialAccount了,而不再是Account。
            43 s = SpecialAccount:new{limit = 1000.00}
            44 --在調用下面的deposit方法時,由于table s和SpecialAccount均未提供該方法,因此訪問的仍然是
            45 --Account的deposit方法。
            46 s:deposit(100)
            47
            48
            49 --此時的withdraw方法將不再是Account中的withdraw方法,而是SpecialAccount中的該方法。
            50 --這是因為Lua先在SpecialAccount(即s的元表)中找到了該方法。
            51 s:withdraw(200.00)
            52 print(s.balance) --輸出-100
            復制代碼


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

            復制代碼
             1 --這里我們需要一個閉包函數作為類的創建工廠
            2 function newAccount(initialBalance)
            3 --這里的self僅僅是一個普通的局部變量,其含義完全不同于前面示例中的self。
            4 --這里之所以使用self作為局部變量名,也是為了方便今后的移植。比如,以后
            5 --如果改為上面的實現方式,這里應用了self就可以降低修改的工作量了。
            6 local self = {balance = initialBalance} --這里我們可以將self視為私有成員變量
            7 local withdraw = function(v) self.balance = self.balance - v end
            8 local deposit = function(v) self.balance = self.balance + v end
            9 local getBalance = function() return self.balance end
            10 --返回對象中包含的字段僅僅為公有方法。事實上,我們通過該種方式,不僅可以實現
            11 --成員變量的私有性,也可以實現方法的私有性,如:
            12 --local privateFunction = function() --do something end
            13 --只要我們不在輸出對象中包含該方法的字段即可。
            14 return {withdraw = withdraw, deposit = deposit, getBalance = getBalance}
            15 end
            16
            17 --和前面兩個示例不同的是,在調用對象方法時,不再需要self變量,因此我們可以直接使用點(.),
            18 --而不再需要使用冒號(:)操作符了。
            19 accl = newAccount(100.00)
            20 --在函數newAccount返回之后,該函數內的“非局部變量”表self就不再能被外部訪問了,只能通過
            21 --該函數返回的對象的方法來操作它們。
            22 accl.withdraw(40.00)
            23 print(acc1.getBalance())
            復制代碼

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

            posted on 2014-02-17 17:41 沛沛 閱讀(280) 評論(0)  編輯 收藏 引用 所屬分類: Script
            A级毛片无码久久精品免费| 久久99精品国产| 亚洲欧洲精品成人久久曰影片| 久久精品女人天堂AV麻| 久久精品国产久精国产果冻传媒| 亚洲AV日韩精品久久久久久| 99久久精品费精品国产| 99re久久精品国产首页2020| 91精品久久久久久无码| 久久婷婷色香五月综合激情| 精品乱码久久久久久久| 久久国产香蕉视频| 国产情侣久久久久aⅴ免费| 精品无码久久久久久久动漫| 亚洲AV日韩精品久久久久| 亚洲国产成人精品91久久久 | 99久久精品无码一区二区毛片| 亚洲精品成人网久久久久久| 99精品国产在热久久无毒不卡 | 久久精品国产亚洲麻豆| 18禁黄久久久AAA片| 国产精品久久自在自线观看| 中文精品久久久久人妻不卡| 亚洲AⅤ优女AV综合久久久| 久久国产一区二区| 久久久精品2019免费观看| 国产精品久久久香蕉| 亚洲精品tv久久久久久久久久| 青青青青久久精品国产h| 久久精品国产91久久综合麻豆自制 | 九九久久精品国产| 国产精品岛国久久久久| 伊人色综合久久天天| 思思久久精品在热线热| 综合久久精品色| 久久综合亚洲色HEZYO社区| 一个色综合久久| 亚洲美日韩Av中文字幕无码久久久妻妇 | 伊人久久大香线蕉亚洲| 亚洲AV无码久久精品成人| 亚洲狠狠婷婷综合久久久久|