Lua 面向对象-程序员宅基地

技术标签: lua  开发语言  

一,简介

面向对象编程是一种非常流行的计算机编程架构,但是lua 没有具体的类去实现。
先说说面向对象的特征。

1,面向对象特征

1) 封装:指能够把一个实体的信息、功能、响应都装入一个单独的对象中的特性。
2) 继承:继承的方法允许在不改动原程序的基础上对其进行扩充,这样使得原功能得以保存,而新功能也得以扩展。这有利于减少重复编码,提高软件的开发效率。
3) 多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
4)抽象:抽象(Abstraction)是简化复杂的现实问题的途径,它可以为具体问题找到最恰当的类定义,并且可以在最恰当的继承级别解释问题

2, lua的特性

Lua 最基本的结构是Table ,对象的组成是属性和方法,所以需要用table来描述对象的属性。
function 是lua 中用来定义方法函数的。故此类的实现是可以用lua 的Table + function模拟出来。
继承:可以借助setmetatable(元表)来实现。

3,lua 元表Metatable

lua table 是以键值对的形式存在,如果两表相加,则需要通过元表Metatable进行。
当 Lua 试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫 __add 的字段,若找到,则调用对应的值。 __add 等即时字段,其对应的值(往往是一个函数或是 table)就是"元方法"。
有两个很重要的函数来处理元表:
setmetatable(table,metatable): 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败。
getmetatable(table): 返回对象的元表(metatable)。

如:

myTabel = {}
my_metable = {}
setmetatable(myTabel , my_metable )

上述中会将my_metable 表设置为myTabel 的子表(元素)。

__index:
当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。
如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。
__index 元方法查看表中元素是否存在,如果不存在,返回结果为 nil;如果存在则由 __index 返回结果。

mytable = setmetatable({key1 = "value1"}, {
  __index = function(mytable, key)
    if key == "key2" then
      return "metatablevalue"
    else
      return nil
    end
  end
})

print(mytable.key1,mytable.key2)


--- 输出结果 为
value1    metatablevalue


也可以将其简写为
mytable = setmetatable({key1 = "value1"}, { __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)

实例解析:
mytable 表赋值为 {key1 = “value1”}。
mytable 设置了元表,元方法为 __index。
在mytable表中查找 key1,如果找到,返回该元素,找不到则继续。
在mytable表中查找 key2,如果找到,返回 metatablevalue,找不到则继续。
判断元表有没有__index方法,如果__index方法是一个函数,则调用该函数。
元方法中查看是否传入 “key2” 键的参数(mytable.key2已设置),如果传入 “key2” 参数返回 “metatablevalue”,否则返回 mytable 对应的键值。
我们可以将以上代码简单写成:

总结
Lua 查找一个表元素时的规则,其实就是如下 3 个步骤:
1.在表中查找,如果找到,返回该元素,找不到则继续
2.判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。
3.判断元表有没有 __index 方法,如果 __index 方法为 nil,则返回 nil;如果 __index 方法是一个表,则重复 1、2、3;如果 __index 方法是一个函数,则返回该函数的返回值。

__newindex:
此方法是用于对表做更新操作,__index 是用来对表进行访问/
当对表中缺少的索引赋值,解释器会先查找__newindex,如果存在,就调用这个函数而不进行赋值,

mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })

print(mytable.key1) --- value1

mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey) ---nil    新值2

mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)  -----新值1    nil




lua 表得基本操作符
模式 描述
__add 对应的运算符 ‘+’.
__sub 对应的运算符 ‘-’.
__mul 对应的运算符 ‘*’.
__div 对应的运算符 ‘/’.
__mod 对应的运算符 ‘%’.
__unm 对应的运算符 ‘-’.
__concat 对应的运算符 ‘…’.
__eq 对应的运算符 ‘==’.
__lt 对应的运算符 ‘<’.
__le 对应的运算符 ‘<=’.

-- 自定义计算表中最大键值函数 table_maxn,即返回表最大键值
function table_maxn(t)
    local mn = 0
    for k, v in pairs(t) do
        if mn < k then
            mn = k
        end
    end
    return mn
end

-- 两表相加操作
myTesttable = setmetatable({ 1, 2, 3 }, {
  __add = function(myTesttable , newtable)
    for i = 1, table_maxn(newtable) do
      table.insert(myTesttable , table_maxn(myTesttable )+1,newtable[i])
    end
    return myTesttable 
  end
})

secondtable = {4,5,6}

myTesttable = myTesttable + secondtable
for k,v in ipairs(myTesttable ) do
	print(k,v)
end

---结果如下
1    1
2    2
3    3
4    4
5    5
6    6

回归正题 模仿类得实现

---classname 创建得类名,super继承
function class(classname, super)
    local superType = type(super)
    local cs

    if superType ~= "function" and superType ~= "table" then
        superType = nil
        super = nil
    end
    if superType == "function" or (super and super.__ctype == 1) then
        -- inherited from native C++ Object
        cs = {}

        if superType == "table" then
            -- copy fields from super
            if super ~= nil then
                for k, v in pairs(super) do
                    cs[k] = v
                end
                cs.__create = super.__create
                cs.super = super
            end
        else
            if super then
                cs.__create = super
            end
        end

        cs.ctor = function()
        end
        cs.__cname = classname
        cs.__ctype = 1

        function cs.new(...)
            local instance = cs.__create(...)
            -- copy fields from class to native object
            for k, v in pairs(cs) do
                instance[k] = v
            end
            instance.class = cs
            instance:ctor(...)
            return instance
        end
    else
        -- inherited from Lua Object
        if super then
            cs= clone(super)
            cs.super = super
        else
            cs= {
                ctor = function()
                end
            }
        end

        cs.__cname = classname
        cs.__ctype = 2 -- lua
        cs.__index = cls

        function cs.new(...)
            local instance = setmetatable({}, cs)
            instance.class = cs
            instance:ctor(...)
            return instance
        end
    end

    return cs
end

Class的使用

---@class ParentView 
local ParentView = _G.class("ParentView ")
----create----------------------------------------------------------------
function ParentView :create()
    local instance = ParentView :new()
    if nil ~= instance and instance:init() then
        instance:onLoaded("ParentView ")
        return instance
    end
end



----init----------------------------------------------------------------
function ParentView :init()
    return true
end

----onEnter----------------------------------------------------------------
function ParentView :onEnter()
    self:onEvent()
    self:ininView()
end


function ParentView :TestEvent2()
    Log.d("Edric ...test LMBJTEST ...22222222222222222.")
end

--- test 
function ParentView :TestEvent()
    Log.d("Edric ...test LMBJJieBiaoDaTingView ....")
end

function ParentView :onExit()

end

return ParentView 


继承

---@class LMBJTEST : ParentView 
local ParentView = require "path" --- 父类得路径
local LMBJTEST = class("LMBJTEST", function()
    local ArmyNode = ParentView :create()
    -- self.superP = ArmyNode
    return ArmyNode
end)
LMBJTEST.__index = LMBJTEST
function LMBJTEST:create()
    local instance = LMBJTEST:new()
    if instance:init() then
        return instance
    end
    return nil
end

function LMBJTEST:init()
    return true
end

--- 重写父类方法, 父类方法的内容 不会直接调用,需全部重写
-- function LMBJTEST:onEnter()
--     self.__create():onEnter()
-- end

function LMBJTEST:TestEvent()
    Log.d("Edric ...test LMBJTEST ....")
    ---- 调用父类方法
    self:TestEvent2()
    
end

return LMBJTEST
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/IT5666/article/details/138028298

智能推荐

umi命令行工具源码解读,umi build打包-程序员宅基地

文章浏览阅读1.3w次。以umi build为例,查看umi命令行工具的逻辑首先查看package.json文件的bin字段,找到umi可执行文件的位置: "bin": { "umi": "./bin/umi.js" },查看umi/bin/umi.js文件,实际逻辑是在umi/src/cli.js文件中,执行umi build// umi/src/cli.jsswitch (script) ..._umi build

Drools 7 用OOPath遍历嵌套类型的实体对象-程序员宅基地

文章浏览阅读1.1k次。Drools 7 基于XPath的OOPath用于简化对象或者内层嵌套的对象属性的遍历。这个话题很拗口,简单点讲就是一种带有筛选条件的访问实体或实体内部嵌套的实体及其属性的方式_oopath

你时间总不够用?请收下这套最佳的分配时间的方法-程序员宅基地

文章浏览阅读399次。有谁要是为了赚得更多的钱而加班加点、 更加卖力地去工作, 他就不会真正变得更加富有。 被牺牲掉的业余时间的价值必须从其更高收入中扣除, 而且被牺牲掉的这部分的价值通常比财务上得到的要高很多。为了赚更多的钱而牺牲掉您的业余时间, 靠这种方法您不可能实现真正的富有。 真正的富有是指具有由少变多的本事, 而并非必须为此做出同样程度的牺牲。真正的成功意味着: 您能够获得更高的收入, 但您的...

错误处理:MySQL报错解决:插入数据时发生错误-程序员宅基地

文章浏览阅读2.2k次。大家好,今天我来分享一下在Linux上运行MySQL服务时遇到的一个插入数据时的报错以及其解决方法。这个报错信息非常具体,相信很多开发者和运维人员都曾经遇到过。记得关注我的公众号“运维家”,获取更多实用技巧和经验分享。一、问题描述当你尝试向MySQL数据库中插入数据时,可能会遇到以下报错信息:“无法插入数据,因为字段不匹配”。这时候,你可能会感到困惑,因为你明明已经按照正确的格式提供了数据,为什么..._mysql数据添加数据报错

idea插件 监听编辑板块切换_ideaeditor编辑监听-程序员宅基地

文章浏览阅读1.8k次。监听编辑板块切换开发工具:IntellJ Idea 开发语言:Kotlin功能描述:实现监听编辑板块切换效果图: 打印日志: 下面是实现该功能的代码: com.your.company.unique.plugin.id Djy 1.0

MAC下配置SSH免密登录及相关报错_mac ssh-rsa-程序员宅基地

文章浏览阅读418次。MAC下配置SSH免密登录及相关报错_mac ssh-rsa

随便推点

vue使用UEditor富文本_vue富文本ueditor学习-程序员宅基地

文章浏览阅读428次。UEditor 使用_vue富文本ueditor学习

Android_8.1 Log 系统源码分析_liblog.so 源码包-程序员宅基地

文章浏览阅读1k次,点赞2次,收藏6次。0x01 Android Log框架推荐1、 logger提供了一些格式化输出、美观// 添加依赖implementation 'com.orhanobut:logger:2.2.0'// 初始化Logger.addLogAdapter(new AndroidLogAdapter());// 使用Logger.d("hello,Android");2、timber基于原生L..._liblog.so 源码包

愉快地迁移到 Python 3-程序员宅基地

文章浏览阅读1.5k次。(点击上方公众号,可快速关注)编译: Python开发者 - 冲动老少年 英文:Alex Rogozhnikovhttp://python.jobbole.com/89031/为数据科学家准备的 Python 3 特性指南Python 已经成为机器学习和一些需处理大量数据的科学领域的主流语言。它支持了许多深度学习框架和其他已确立下来的数据处理和可视化的工具集。然而,Python 生态系统还处_如何迁移到python 3.x

Python之 Django 模板渲染Template_templates渲染|safe-程序员宅基地

文章浏览阅读2.2k次。1. Django自带模板1.1 配置在工程中创建模板目录templates。在项目settings.py配置文件中修改TEMPLATES配置项的DIRS值:# 基本配置TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': _templates渲染|safe

基于CEVA DSP BX2的架构分析(一)_ceva sdt-程序员宅基地

文章浏览阅读1.1k次,点赞35次,收藏21次。仿真、验证、合成和布局环境以及高级文档都包含在交付中,作为客户的参考,以实现核心的快速平滑集成。通信技术采用了更高的频段和更大的带宽,可以实现更高的数据传输速率和更低的延迟。通信技术需要支持更大的网络容量和更低的能耗,这要求基带处理器具备高效的能源管理能力,包括低功耗设计和智能能源管理等。通信技术需要支持多种不同的应用场景和业务类型,这要求基带处理器具备灵活性和可扩展性,能够适应不同的应用需求。通信技术需要支持高可靠性和稳定性的业务,这要求基带处理器具备高可靠性和稳定性,能够保证业务的正常运行。_ceva sdt

【张朝阳的物理课笔记】 3. 光的散射,天空的蓝色,早晚太阳是红色的原因_光线散射 公式-程序员宅基地

文章浏览阅读997次。散射光能量和入射光频率的4次方成正比,所以蓝光紫光比红光更容易被散射_光线散射 公式

推荐文章

热门文章

相关标签