lua的面向對象編程

    首先咱們去了解一下類,一個類就是一個建立對象的模具,實際上,lua中不存在類這個概念,咱們都是去模擬類。在lua中,要表示一個類,只需建立一個專用做其它對象的原型。咱們在lua的面相對象,就是使用table,元表以及元方法,咱們如今看一下具體事怎麼作的:
編程

    咱們如今有兩個對象a和b,如今想b做爲a的原型,只需編寫下面代碼便可:函數

setmetatable(a,{__index = b})

    咱們前面有講過__index,編寫完這段代碼以後,當lua執行了a沒有的操做的時候,就會去b中查詢。實際上咱們也能夠稱b事對象a的類;咱們要建立一個對象,必需要有一個原型,這就是「類」。以下:lua

local man = {num = 0}

    如今咱們有原型類,接着咱們使用這個原型建立一個「實例」,首先咱們先編寫man的new函數:spa

function man:new(o)
    o = o or {}    --若是o爲nil,則將o複製爲{}
    setmetatable(o,self)
    self.__index = self
    return o
end

function man:sayhi()
    self.num = self.num + 1
    print("已經打招呼的人" .. self.num)
end

    當咱們調用man的new函數的時候,self就至關於man。接着咱們來使用man的new函數來建立一個實例:code

local tom = man:new()
tom:sayhi()
tom:sayhi()

   輸出:對象

已經打招呼的人1
已經打招呼的人2

     咱們來看一下上面的代碼如何工做的,首先使用man的new函數去建立一個新的實例對象,並將man做爲新的實例對象tom的元表。當咱們調用tom:sayhi()時,lua就會去查找tom是否有sayhi這個字段,沒有的話就去搜索它的元表,調用的結果其實是:
繼承

getmetatable(tom).__index(sayhi(tom))

    而tom的元表是man,man的__index也是man,上面的寫法實際上也是:get

man.sayhi(tom)

    實際上,咱們上面也是涉及到了繼承的(sayhi函數)。接着咱們來探討一下lua的多繼承:
原型

   咱們能夠能夠設置子類的metatable爲父類,並將父類的__index設置爲其自己來實現單繼承。而多繼承也是同樣的道理,不一樣的是單繼承中若是子類沒有對應的字段,則只需在一個父類中尋找這個不存在的字段,而多繼承則是須要在多個父類中尋找。io

    因爲多繼承須要在多個父類中尋找,因此咱們不能像單繼承那樣,直接指向__index爲某個父類,而是應該指定__index爲一個函數,在這個函數中指定搜索不存在的字段的規則。這樣即可以實現多繼承。咱們看一下下面的例子:

-- 在多個父類中查找字段k
local function search(k, pParentList)
    for i = 1, #pParentList do
        local v = pParentList[i][k]
        if v then
            return v
        end
    end
end

function createClass(...)
    local c = {} -- 新類
    local parents = {...}

    -- 類在其元表中搜索方法
    setmetatable(c, {__index = function (t, k) return search(k, parents) end})

    -- 將c做爲其實例的元表
    c.__index = c

    -- 爲這個新類創建一個新的構造函數
    function c:new(o)
        o = o or {}
        setmetatable(o, self)

        -- self.__index = self 這裏不用設置了,在上面已經設置了c.__index = c
        return o
    end

    -- 返回新的類(原型)
    return c
end

-- 一個簡單的類CA
local CA = {}
function CA:new(o)
    o = o or {}
    setmetatable(o, {__index = self})
    self.__index = self
    return o
end

function CA:setName(strName)
    self.name = strName
end

-- 一個簡單的類CB
local CB = {}
function CB:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
end

function CB:getName()
    return self.name
end

-- 建立一個c類,它的父類是CA和CB
local c = createClass(CA, CB)

-- 使用c類建立一個實例對象
local objectC = c:new{name = "Jelly"}

-- 設置objectC對象一個新的名字
objectC:setName("JellyThink")
local newName = objectC:getName()
print(newName)

    注:

  1. 使用createClass建立了一個類(原型),將CA和CB設置爲這個類(原型)的父類(原型);在建立的這個類(原型)中,設置了該類的__index爲一個search函數,在這個search函數中尋找在建立的類中沒有的字段;

  2. 建立的新類中,有一個構造函數new;這個new和以前的單繼承中的new區別不大,很好理解;

  3. 調用new構造函數,建立一個實例對象,該實例對象有一個name字段;

  4. 調用object:setName(「JellyThink」)語句,設置一個新的名字;可是在objectC中沒有這個字段,怎麼辦?好了,去父類找,先去CA找,一會兒就找到了,而後就調用了這個setName,setName中的self指向的是objectC;設置之後,就至關於修改了objectC字段的name值;

  5. 調用objectC:getName(),objectC仍是沒有這個字段。找吧,CA也沒有,那就接着找,在CB中找到了,就調用getName,在getName中的self指向的是objectC。因此,在objectC:getName中返回了objectC中name的值,就是「JellyThink」。

    其實lua的類就是建立一個table,而後爲table綁定幾個方法,綁定幾個對象。而後在經過元表與元方法的一些操做從而完成lua的面相對象編程。

相關文章
相關標籤/搜索