写在前面

  • 最近在琢磨“Lua热重载”,在测试中发现我之前对Lua中的面向对象实现有一些理解发生变化,这里记录一下。
  • 本文提到的面向对象实现来自云风

类实现

  • 《Lua程序设计(第4版)》以银行账户存取钱为例,解释了如何实现一个类。从“面向对象的3大特性”角度,它的实现概括如下:

    • 继承:改__index引向自己
    • 多态:不用新建其他类,会自动找到对应方法(多重继承,书上举例是用查找父类方法实现的)
    • 封装:
      • 单方法:将公开的字段和函数放在单独表中;不过这种方式不能“继承”。
      • 对偶:把表当key存起来;可“继承”。
  • 不过《Lua程序设计(第4版)》书上没有完整的可直接拷走的代码,我工作项目用的是toLua,toLua也没有提供Lua类脚本,所以用了云风设计的class代码,如下:
local _class={}

function class(super)
local class_type={}
class_type.ctor=false
class_type.super=super
class_type.new=function(...)
local obj={}
do
local create
create = function(c,...)
if c.super then
create(c.super,...)
end
if c.ctor then
c.ctor(obj,...)
end
end create(class_type,...)
end
setmetatable(obj,{ __index=_class[class_type] })
return obj
end
local vtbl={}
_class[class_type]=vtbl setmetatable(class_type,{__newindex=
function(t,k,v)
vtbl[k]=v
end
}) if super then
setmetatable(vtbl,{__index=
function(t,k)
local ret=_class[super][k]
vtbl[k]=ret
return ret
end
})
end return class_type
end

理解

  • 对比:有对比才能看出云风写的class好在哪,之前我在看LuaFramework_UGUI框架时,它有一个写的很短很简单的LuaClass(如下),拿LuaClass和云风的对比,能看得出来LuaClass在“面向对象的3大特性”上没有实现“多态”和“封装”,LuaClass仅能作为参考,是不能直接搬到正式工程里用的。
--Author : Administrator
--Date : 2014/11/25 --声明,这里声明了类名还有属性,并且给出了属性的初始值。
LuaClass = {x = 0, y = 0} --这句是重定义元表的索引,就是说有了这句,这个才是一个类。
LuaClass.__index = LuaClass --构造体,构造体的名字是随便起的,习惯性改为New()
function LuaClass:New(x, y)
local self = {}; --初始化self,如果没有这句,那么类所建立的对象改变,其他对象都会改变
setmetatable(self, LuaClass); --将self的元表设定为Class
self.x = x;
self.y = y;
return self; --返回自身
end --测试打印方法--
function LuaClass:test()
logWarn("x:>" .. self.x .. " y:>" .. self.y);
end --endregion
  • 回到class,最开始阅读class代码时,我有好些地方没看懂,包括“_class是放什么的”,“class_type为什么要起名叫class_type”等等。最近在琢磨“Lua热重载”时,再次回顾了这里,对以前理解错误的地方或是一知半解的问题有了新回答。以下是我在阅读时冒出的问题和对应回答:

    • _class是什么?——> _class是记录各种类的类型(以下都称为“类-原型”)的词典(如果是我,会起名为_classTypeMap,这样更好懂)。

      • 比如:新建两个类-原型A和B,此时_class中会记有类-原型A和类-原型B。
local A = class()
local B = class()     
    • class()到底做了什么?——> class()其实负责的是创建“类-原型”,而非“类-实例”,这从它最后return的值是class_type可以看出。如果需要创建“类-实例”,就得用new函数。
    • 下面的代码是什么意思?——> vtbl 即value table,setmetatable这里对class_type有写操作,却无读操作,即class_type里的数据是只写属性,即这些数据仅限于类内部使用。
local vtbl={}
_class[class_type]=vtbl setmetatable(class_type,{__newindex=
function(t,k,v)
vtbl[k]=v
end
})

    有需要的话,可以修改,例如下方就是把原来的只写属性改为可读可写属性,即public:

local vtbl = {}
_class[class_type] = vtbl setmetatable(class_type, {
__newindex = function(t,k,v)
vtbl[k] = v
end, __index = vtbl,
})
    • 下面的代码是什么意思?——> 查找自己没有的数据时,如果有父类super,先去_class里找类-原型super的数据,拿该数据覆盖/填充
if super then
setmetatable(vtbl,{__index=
function(t,k)
local ret=_class[super][k]
vtbl[k]=ret
return ret
end
})
end
  • 根据上面回答,以下是我加了注释的class代码:
-- https://blog.codingnow.com/cloud/LuaOO
-- 类(注释版) -- _class是记录各种类的类型(以下都称为“类-原型”)的词典
-- 比如:local A = class(),local B = class(),则_class中会记有类-原型A和类-原型B
-- 如果是我,会起名为_classTypeMap,这样更好懂
local _class = {} function class(super)
-- 创建的是类-原型class_type,只有用了类-原型的new函数,才能得到类-实例
local class_type = {}
-- 自定义构造函数ctor
class_type.ctor = false
class_type.super = super
class_type.new = function(...)
local obj = {}
do
local create = function(c, super)
if c.super then
create(c.super, ...)
end
if c.ctor then
c.ctor(obj, ...)
end
end
create(class_type, ...)
end
-- 在_class中查找类-类型为class_type的数据
setmetatable(obj, {__index = _class[class_type]})
return obj
end -- vtbl即value table
local vtbl = {}
_class[class_type] = vtbl
-- 对class_type有写操作,却无读操作,即class_type里的数据是只写属性,即这些数据仅限于类内部使用
-- (可见《Lua程序程序设计(第4版)》第21章“面向对象编程”的“对偶”)
setmetatable(class_type,
{
__newindex = function(t, k, v)
vtbl[k] = v
end }) -- 查找自己没有的数据时,如果有父类super,先去_class里找类-原型super的数据,拿该数据覆盖/填充
if super then
setmetatable(vtbl,
{
__index = function(t, k)
local ret = _class[super][k]
vtbl[k] = ret
return ret
end })
end return class_type end

关于Lua中的面向对象实现的更多相关文章

  1. Cocos2d-x 脚本语言Lua中的面向对象

    Cocos2d-x 脚本语言Lua中的面向对象 面向对象不是针对某一门语言,而是一种思想.在面向过程的语言也能够使用面向对象的思想来进行编程. 在Lua中,并没有面向对象的概念存在,没有类的定义和子类 ...

  2. lua中的面向对象编程

    简单说说Lua中的面向对象 Lua中的table就是一种对象,看以下一段简单的代码: 上述代码会输出tb1 ~= tb2.说明两个具有相同值得对象是两个不同的对象,同时在Lua中table是引用类型的 ...

  3. Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 在 ...

  4. 【转载】【游戏开发】在Lua中实现面向对象特性——模拟类、继承、多态

    [游戏开发]在Lua中实现面向对象特性——模拟类.继承.多态   阅读目录 一.简介 二.前提知识 三.Lua中实现类.继承.多态 四.总结 回到顶部 一.简介 Lua是一门非常强大.非常灵活的脚本语 ...

  5. Lua中的面向对象编程详解

    简单说说Lua中的面向对象 Lua中的table就是一种对象,看以下一段简单的代码: 复制代码代码如下: local tb1 = {a = 1, b = 2}local tb2 = {a = 1, b ...

  6. lua 中的面向对象

    lua 是一种脚步语言,语言本身并不具备面向对象的特性. 但是我们依然可以利用语言的特性,模拟出面向对象的特性. 面向对象的特性通常会具备:封装,继承,多态的特性,如何在lua中实现这些特性,最主要的 ...

  7. 【游戏开发】在Lua中实现面向对象特性——模拟类、继承、多态

    一.简介 Lua是一门非常强大.非常灵活的脚本语言,自它从发明以来,无数的游戏使用了Lua作为开发语言.但是作为一款脚本语言,Lua也有着自己的不足,那就是它本身并没有提供面向对象的特性,而游戏开发是 ...

  8. Lua 中使用面向对象(续)

    上一篇文章给了一个面向对象的方案,美中不足的是没有析构函数 Destructor,那么这一次就给它加上. 既然是析构,那么就是在对象被销毁之前做该做的事情,lua 5.1 的 userdata 可以给 ...

  9. Lua中的userdata

    [话从这里说起] 在我发表<Lua中的类型与值>这篇文章时,就有读者给我留言了,说:你应该好好总结一下Lua中的function和userdata类型.现在是时候总结了.对于functio ...

  10. 9----Lua中的面向对象

    什么是面向对象? 使用对象.类.继承.封装.消息等基本概念来进行程序设计 面向对象最重要的两个概念就是:对象和类 对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位 一个对象由一组属性 ...

随机推荐

  1. 邮件合并 :处理ACCESS中批量查询语句的运行

    利用邮件合并,制作批量查询语句,一条一条的复制粘贴并运行. 有点笨但是想不出什么好办法,除非用模块的过程,但还是要手动输入参数.http://www.docin.com/p-695725657.htm ...

  2. Rocky linux command-1

    在Linux下一切皆文件 everything is file,包括目录也是文件的一种而这些文件被分为七种类型: • -:普通文件 • d: 目录文件 • b: 块设备 • c: 字符设备 • l:  ...

  3. 暴雪、迪士尼大佬用什么画画?RayLink远控软件助力解锁远程创作

    CG绘画从业者,如原画师.插画师.漫画家.设计师等,一定对数位板\数位屏不陌生,数位板\数位屏是完成CG绘画作品的重要绘图工具之一. 从画画小白到数字绘画大神,从0基础插画培训班学生到国际知名游戏.动 ...

  4. Xpath 常用语法展示

    非标准代码处理 from lxml import etree #导入lxml 中erree模块 parser = etree.HTMLParser(encoding="utf-8" ...

  5. Oracle ASM磁盘组的常用操作

    1.查看现有磁盘组信息 select group_number gno,name,state,type,total_mb,free_mb,required_mirror_free_mb rmfmb,u ...

  6. 2022-3-16内部群每日三题-清辉PMP

    1.项目经理正在为客户管理一个跨国项目,拟采用最新技术替换其电信基础设备.项目经理得知,在某些国家,必须遵循特定的环境规定来处置被替换的硬件.在制定商业论证时,未考虑到这些规定,项目经理应该怎么做? ...

  7. (jmeter笔记)jmeter监控服务器资源

    jmeter版本:5.2.1 jdk版本:1.8.0_191 监控服务器的CPU/memory.IO.硬盘等信息 1.下载jmeter-plugins-manager-1.4.jar 插件,解压之后把 ...

  8. mysql 设置外键约束SET FOREIGN_KEY_CHECKS=1

    问题描述:Mysql中如果表和表之间建立的外键约束,则无法删除表及修改表结构 解决方法: 在Mysql中取消外键约束: SET FOREIGN_KEY_CHECKS=0; 然后将原来表的数据导出到sq ...

  9. Java面向对象编程:多态(自我理解)

    多态 (1)概念:同一个行为具有多个不同表现形式或形态的能力:就是同一个接口,使用不同的实例而执行不同的操作. (2)优点:消除类型之间的耦合关系:可替换性:可扩充性:接口性:灵活性:简化性: (3) ...

  10. Jenkins启动失败的七个问题

    1.jdk版本和路径问题(注意第6个问题) which java vim /etc/init.d/jenkins 2.用户名问题 查看/etc/sysconfig/jenkins的JENKINS_US ...