麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 開發(fā) > 綜合 > 正文

Lua面向?qū)ο笾嘀乩^承、私密性詳解

2024-07-21 23:04:04
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

在Lua中的多重繼承和私密性可能用得比較少,也可能只是我個(gè)人用得比較少。
本來(lái)想偷懶不寫這文章的,因?yàn)槲医裉靹傎I了個(gè)漂移板,連起步都還沒(méi)學(xué)會(huì)啊,想多學(xué)一會(huì)。

咳咳,本著堅(jiān)持不懈、負(fù)責(zé)到底的態(tài)度,我還是決定隨便寫幾句~(小若:隨便寫幾句是幾噸意思啊?!)

1.多重繼承之在多個(gè)類中查找一個(gè)字段

我發(fā)現(xiàn)這些高(shen)智(jing)商(bing)人群真的很厲害,這種技巧都能想到,很佩服。
其實(shí)多重繼承沒(méi)什么特別的,除非兩個(gè)將要被繼承的類有相同的函數(shù)名和屬性,否則,處理起來(lái)很簡(jiǎn)單。
 
無(wú)非就是在多個(gè)table中查找某個(gè)字段而已,不簡(jiǎn)單嗎?Lua里的繼承就是在別人的table里查找自己不存在的字段罷了。

那么,單繼承與多重繼承的差別也在這里,一個(gè)是只查找一個(gè)table,另一個(gè)是查找兩個(gè)或以上的table。

我們就先來(lái)看看如何從2個(gè)或多個(gè)table中查找某個(gè)字段,如下代碼:

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

function search(classes, key)
    for i = 1, #classes do
        local value = classes[i][key];
        if value ~= nil then
            return value;
        end
    end
end
local t1 = {name = "hehe"};
local t2 = {game = "who"};
print(search({t1, t2}, "game"));

 

這里的classes參數(shù),是一個(gè)table,這個(gè)table里又存放了多個(gè)table,也就是我們想要繼承的那些類。

而key就是要查找的字段。

只需要遍歷所有的table,判斷這個(gè)字段是否在某個(gè)table里,找到之后,就返回這個(gè)值。
我們的測(cè)試代碼就是從t1、t2中查找game這個(gè)字段,t1、t1可以看成是兩個(gè)類。
輸出結(jié)果如下:

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

[LUA-print] who

 

2.多重繼承之創(chuàng)建繼承多個(gè)類的子類

剛剛的search函數(shù)很簡(jiǎn)單吧?別急著開心,那只是預(yù)熱一下而已,真正創(chuàng)建多重繼承的函數(shù)比較復(fù)雜。

如下代碼:

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

function createClass(...)
    local parents = {...};
    local child = {};
  
    -- 設(shè)置類的元表
    setmetatable(child, {
        __index = function(table, key)
            return search(parents, key);
        end
    })
  
    -- 給類新增一個(gè)new函數(shù),用于創(chuàng)建對(duì)象
    function child:new()
        o = {};
        setmetatable(o, child);
        child.__index = child;
        return o;
    end
  
    -- 返回這個(gè)繼承了多個(gè)類的子類
    return child;
end

 

createClass函數(shù)就是用來(lái)創(chuàng)建一個(gè)繼承了多個(gè)類的子類,有點(diǎn)小復(fù)雜,慢慢分析:

1) 參數(shù)是一個(gè)可變參數(shù),我們要將多個(gè)被繼承的類作為參數(shù)傳遞進(jìn)來(lái)
2) parents用于保存這些被繼承的類
3) 創(chuàng)建一個(gè)新的table——child,它就是我們想要的那個(gè)繼承了多個(gè)類的子類
4) 給child設(shè)置元表,并且設(shè)置__index元方法,__index元方法可以是一個(gè)函數(shù),當(dāng)它是一個(gè)函數(shù)時(shí),它的參數(shù)就是元表所屬的table,以及要查找的字段名。
5) 我們?cè)赺_index元方法函數(shù)里調(diào)用search函數(shù),從多個(gè)父類中查找所需的字段。于是,當(dāng)調(diào)用child的某個(gè)函數(shù)時(shí),就會(huì)從各個(gè)父類中查找,這已經(jīng)完成了繼承的工作了。
6) 接下來(lái)就是我們所熟悉的new函數(shù),用來(lái)創(chuàng)建child的子類,實(shí)現(xiàn)方式和上一篇所說(shuō)的是一樣 ,如果你忘記了,可以看看這篇文章:http://www.companysz.com/article/55168.htm
7) 最后返回child,一切都完成了。

看似很復(fù)雜,其實(shí)還是對(duì)__index的應(yīng)用而已。

我們趕緊來(lái)測(cè)試一下吧,如下代碼:

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

    --一個(gè)精靈類
    TSprite = {}
    function TSprite:hello()
        print("誰(shuí)跟你hello!");
    end
  
    function TSprite:new()
        o = {}
        setmetatable(o, self);
        self.__index = self;
        return o;
    end
  
    -- 一個(gè)子彈類
    TBullet = {}
    function TBullet:fire()
        print("別動(dòng),再動(dòng)我就瞄不準(zhǔn)了!");
    end
    function TBullet:new()
        o = {}
        setmetatable(o, self);
        self.__index = self;
        return o;
    end
  
    -- 繼承了兩個(gè)類的子類
    local BulletSprite = createClass(TSprite, TBullet);
  
    -- 子類的對(duì)象
    local bSprite = BulletSprite:new();
    bSprite:hello();
    bSprite:fire();

 

這里創(chuàng)建了兩個(gè)類:TSprite和TBullet。
然后調(diào)用createClass函數(shù),創(chuàng)建一個(gè)繼承了TSprite和TBullet的子類。
最后創(chuàng)建子類的對(duì)象,調(diào)用對(duì)象的hello和fire函數(shù)。
輸出結(jié)果如下:

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

[LUA-print] 誰(shuí)跟你hello!
[LUA-print] 別動(dòng),再動(dòng)我就瞄不準(zhǔn)了!

怎么樣?很簡(jiǎn)單吧~

 

3.類的私密性

這里來(lái)說(shuō)一個(gè)和多重繼承無(wú)關(guān)的技巧,那就是私密性。

對(duì)于Java、C++等語(yǔ)言,我們都很熟悉,public、private、protected等關(guān)鍵詞。
這些關(guān)鍵詞讓封裝成為了可能。
 
然后,Lua里是沒(méi)有私密這種說(shuō)法的,類也是一個(gè)table,table的所有字段都是可以調(diào)用的,并沒(méi)有說(shuō)哪些是公有的,哪些是私有的。

如果有某些函數(shù)和屬性不希望被外部調(diào)用,那么,也可以,不過(guò)這種實(shí)現(xiàn)方式看起來(lái)很別扭:

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

function createTSprite()
    local self = {name = "benmutou"};
    local function myBus()
        print("myBus是我自己的函數(shù),你不能直接調(diào)用");
    end
    local function myGame()
        print("myGame是我自己的函數(shù),你不能直接調(diào)用");
    end
    local function hello()
        print("hello:");
        myBus();
    end
    local function hi()
        print("hi:");
        myGame();
    end
  
    local function setName(newName)
        self.name = newName;
    end
  
    return {hello = hello, hi = hi, setName = setName};
end

 

我們已經(jīng)不需要用到冒號(hào)來(lái)定義函數(shù)了,這個(gè)類的name、myBus、myGame都是不希望給外部直接調(diào)用的。

調(diào)用createTSprite函數(shù)后,會(huì)返回一個(gè)新的table,這個(gè)table僅僅存放了一些字段,這些字段就是能夠被外部直接調(diào)用的函數(shù)或者是屬性。

來(lái)看看測(cè)試代碼:

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

    local sp = createTSprite();
    sp.hello();
    sp.hi();

 

輸出結(jié)果如下:

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

[LUA-print] hello:
[LUA-print] myBus是我自己的函數(shù),你不能直接調(diào)用
[LUA-print] hi:
[LUA-print] myGame是我自己的函數(shù),你不能直接調(diào)用

這樣,我們創(chuàng)建的對(duì)象就只能使用hello、hi、setName函數(shù)。

 

而其他的name、myBus、myGame只能通過(guò)這幾個(gè)能使用的函數(shù)去調(diào)用,而不能直接調(diào)用。
這樣就能完成私密性了。
 
不過(guò),我個(gè)人有點(diǎn)迷糊,因?yàn)檫@已經(jīng)不太像一個(gè)類的樣子了。

4.結(jié)束

好了,關(guān)于面向?qū)ο蟮膬?nèi)容,暫時(shí)介紹到這里。
可能介紹的都比較基礎(chǔ),目的是為了鞏固Lua基礎(chǔ)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 九九热视频免费 | 精品中文字幕在线播放 | 亚洲一区二区国产 | 91福利免费观看 | 91精品国产乱码久久桃 | 日韩精品羞羞答答 | 国产精品久久久久久久久久久天堂 | 成人短视频在线观看 | 欧美精品1区 | 一区在线免费视频 | 毛片在哪看 | 黄色7777| 一级在线免费观看视频 | 久久久成人精品视频 | 在线看国产视频 | 天天草夜夜 | 国产黄色录像片 | 久草高清视频 | 久久久久亚洲a | 一区二区三区在线播放视频 | 日韩av成人 | 色域tv| 久久久久久久九九九九 | 亚洲91网站| 精品亚洲一区二区三区 | 亚洲影院在线 | 精品一区二区三区在线播放 | 黄色大片网 | 色婷婷久久一区二区 | 一区二区三区欧美在线 | 欧美一级做a | 国产黄网 | 国产免费最爽的乱淫视频a 毛片国产 | 欧美一级黄色免费看 | 在线播放免费播放av片 | 最新中文在线视频 | 亚洲一区二区三区在线免费观看 | 精品国产一区二区三区四区阿崩 | 国产精品免费小视频 | 美女视频免费一区二区 | 午夜国内精品a一区二区桃色 |