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的面相对象编程。

相关文章
相关标签/搜索