博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
lua的面向对象编程
阅读量:5799 次
发布时间:2019-06-18

本文共 2925 字,大约阅读时间需要 9 分钟。

hot3.png

    首先我们去了解一下类,一个类就是一个创建对象的模具,实际上,lua中不存在类这个概念,我们都是去模拟类。在lua中,要表示一个类,只需创建一个专用作其它对象的原型。我们在lua的面相对象,就是使用table,元表以及元方法,我们现在看一下具体事怎么做的:

    我们现在有两个对象a和b,现在想b作为a的原型,只需编写下面代码即可:

setmetatable(a,{__index = b})

    我们前面有讲过__index,编写完这段代码之后,当lua执行了a没有的操作的时候,就会去b中查询。实际上我们也可以称b事对象a的类;我们要创建一个对象,必须要有一个原型,这就是“类”。如下:

local man = {num = 0}

    现在我们有原型类,接着我们使用这个原型创建一个“实例”,首先我们先编写man的new函数:

function man:new(o)    o = o or {}    --如果o为nil,则将o复制为{}    setmetatable(o,self)    self.__index = self    return oendfunction man:sayhi()    self.num = self.num + 1    print("已经打招呼的人" .. self.num)end

    当我们调用man的new函数的时候,self就相当于man。接着我们来使用man的new函数来创建一个实例:

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,上面的写法实际上也是:

man.sayhi(tom)

    实际上,我们上面也是涉及到了继承的(sayhi函数)。接着我们来探讨一下lua的多继承:

   我们可以可以设置子类的metatable为父类,并将父类的__index设置为其本身来实现单继承。而多继承也是一样的道理,不同的是单继承中如果子类没有对应的字段,则只需在一个父类中寻找这个不存在的字段,而多继承则是需要在多个父类中寻找。

    由于多继承需要在多个父类中寻找,所以我们不能像单继承那样,直接指向__index为某个父类,而是应该指定__index为一个函数,在这个函数中指定搜索不存在的字段的规则。这样便可以实现多继承。我们看一下下面的例子:

-- 在多个父类中查找字段klocal function search(k, pParentList)    for i = 1, #pParentList do        local v = pParentList[i][k]        if v then            return v        end    endendfunction 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 cend-- 一个简单的类CAlocal CA = {}function CA:new(o)    o = o or {}    setmetatable(o, {__index = self})    self.__index = self    return oendfunction CA:setName(strName)    self.name = strNameend-- 一个简单的类CBlocal CB = {}function CB:new(o)    o = o or {}    setmetatable(o, self)    self.__index = self    return oendfunction CB:getName()    return self.nameend-- 创建一个c类,它的父类是CA和CBlocal 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的面相对象编程。

转载于:https://my.oschina.net/u/815187/blog/486053

你可能感兴趣的文章
图的基本算法
查看>>
HTML基础(一)
查看>>
boost.circular_buffer简介
查看>>
Database Appliance并非Mini版的Exadata-还原真实的Oracle Unbreakable Database Appliance
查看>>
网页图片缩放(js)
查看>>
如何用Fiddler对Android应用进行抓包
查看>>
iOS为所需要的视图添加模糊效果--UIVisualEffectView
查看>>
HDU-1222 Wolf and Rabbit (欧几里得定理)
查看>>
Camera Calibration 相机标定:原理简介(五)
查看>>
ehcache实例
查看>>
python 匿名函数
查看>>
javascript实现-------------选择排序
查看>>
centOS中VMware Tools 安装
查看>>
oracle中以dba_、user_、v$_、all_、session_、index_开头的常...
查看>>
leetcode 116- Populating Next Right Pointers in Each Node
查看>>
spring项目启动错误——java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext...
查看>>
iOS开发网络篇—GET请求和POST请求
查看>>
字典dict
查看>>
游戏名词解释
查看>>
mongodb数据的导出和导入
查看>>