lua面向对象

建议提前学习https://www.runoob.com/lua/lua-metatables.html

面向对象特征

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

lua并没有严格的面向对象的语法,我们只是使用表的特性来模拟类。

lua是duck风格,不存在访问性的问题。所以我们这里考虑如下四种概念:

  • 静态变量:属于该类的变量
  • 静态函数:属于该类的函数
  • 成员变量:属于该类对象的变量
  • 成员函数:属于该类对象的函数

一个类是一个元表,表中存储静态变量、静态函数、以及对象的成员函数。

一个对象是一张表,表中存储了成员变量。

如下表:

属于代码位置写法
静态变量元表.
静态函数元表.
成员变量对象.
成员函数对象元表:

示例如下:

A = {             -- 类名为 AstaticVar = 0 -- 静态变量
}
A.__index = A     -- 当做格式即可function A.StaticFunc()                   -- 静态函数print("staticVar is " .. A.staticVar) -- 可以访问静态变量
endfunction A:New(number) -- 定义构造函数,使用其它名称也是可以的-- self 类似 this 指针local obj = {}setmetatable(obj, self)     -- 将对象 obj 的元表设置为类 Aobj.normalVar = number or 0 -- 使用 or 来制定默认值return obj
endfunction A:NormalMethod()                    -- 成员函数print("normalVar is " .. self.normalVar) -- 可以访问成员变量
endlocal a1 = A:New(1) -- 调用构造函数来创建对象
local a2 = A:New(2)
a1.normalVar = 10   -- 修改成员变量
a1:NormalMethod()   -- 调用成员函数
a2:NormalMethod()A:StaticFunc()  -- 通过类名调用静态函数
a1:StaticFunc() -- 通过对象调用静态函数

输出如下:

normalVar is 10
normalVar is 2
staticVar is 0
staticVar is 0

最后补充一个讨论,调用时这两种写法等价:

a1:NormalMethod()   -- 调用普通方法
a1.NormalMethod(a1) -- 等价于上述写法

但是显然第二种写法危险得多,因为可能第二个a1会拼写错误。

类继承

虽然lua不鼓励大家写继承,但是还是能写的。

对于单继承的情况,将子类的元表设置成基类即可。例如:

setmetatable(B, A) -- B 继承了 A

示例如下:

A = {             -- 基类名为 AstaticVar = 0 -- 静态变量
}
A.__index = A     -- 当做格式即可function A.StaticFunc()                   -- 静态函数print("staticVar is " .. A.staticVar) -- 可以访问静态变量
endfunction A:New(number) -- 定义构造函数,使用其它名称也是可以的-- self 类似 this 指针local obj = {}setmetatable(obj, self)     -- 将对象 obj 的元表设置为类 Aobj.normalVar = number or 0 -- 使用 or 来制定默认值return obj
endfunction A:NormalMethod()                    -- 成员函数print("normalVar is " .. self.normalVar) -- 可以访问成员变量
endB = {}             -- 继承类名为 B
B.__index = B      -- 当做格式即可
setmetatable(B, A) -- B 继承了 Afunction B:New(number)               -- 定义构造函数,使用其它名称也是可以的-- self 类似 this 指针local obj = A:New(number)        -- 使用基类的构造函数setmetatable(obj, self)          -- 将对象 obj 的元表设置为类 Bobj.normalVar2 = number + 1 or 0 -- 使用 or 来制定默认值return obj
endfunction B:NormalMethod2()                     -- 成员函数print("normalVar2 is " .. self.normalVar2) -- 可以访问成员变量
endlocal b = B:New(1) -- 调用构造函数来创建对象
b.normalVar = 10   -- 修改成员变量
b:NormalMethod()   -- 调用成员函数
b.normalVar2 = 11
b:NormalMethod2()
b.StaticFunc() -- 可以通过派生类对象访问基类的静态函数

输出如下:

normalVar is 10
normalVar2 is 11
staticVar is 0

覆盖

另外,由于__index寻址的问题,子类的同名函数会覆盖基类的函数。例如:

A = {             -- 基类名为 AstaticVar = 0 -- 静态变量
}
A.__index = A     -- 当做格式即可function A:New(number) -- 定义构造函数,使用其它名称也是可以的-- self 类似 this 指针local obj = {}setmetatable(obj, self)     -- 将对象 obj 的元表设置为类 Aobj.normalVar = number or 0 -- 使用 or 来制定默认值return obj
endfunction A:NormalMethod()                    -- 成员函数print("normalVar is " .. self.normalVar) -- 可以访问成员变量
endB = {}             -- 继承类名为 B
B.__index = B      -- 当做格式即可
setmetatable(B, A) -- B 继承了 Afunction B:New(number)               -- 定义构造函数,使用其它名称也是可以的-- self 类似 this 指针local obj = A:New(number)        -- 使用基类的构造函数setmetatable(obj, self)          -- 将对象 obj 的元表设置为类 Bobj.normalVar2 = number + 1 or 0 -- 使用 or 来制定默认值return obj
endfunction B:NormalMethod()                      -- 成员函数print("normalVar2 is " .. self.normalVar2) -- 可以访问成员变量
endlocal b = B:New(1) -- 调用构造函数来创建对象
b:NormalMethod()   -- 调用成员函数

输出结果为:

normalVar2 is 2

而不是:

normalVar is 1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/12360.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图的深度优先遍历

way:栈,map(或set,只是我想用map)记录是否访问过,放入时记录为已访问,打印,邻接的没访问过先入cur,再入邻接的节点,放入一个邻接的节点后及时break去下一个深…

Kubernetes二进制(单master)部署

文章目录 Kubernetes二进制(单master)部署一、常见的K8S部署方式1. Minikube2. Kubeadmin3. 二进制安装部署4. 小结 二、K8S单(Master)节点二进制部署1. 环境准备1.1 服务器配置1.2 关闭防火墙1.3 修改主机名1.4 关闭swap1.5 在/e…

(done) 关于 pytorch 代码里常出现的 batch_first 到底是啥?

参考文章:https://pytorch.org/docs/stable/generated/torch.nn.utils.rnn.pad_sequence.html 首先看参考文章里的解释,如下图 从文章描述来看,当 batch_first True 时,输出的张量的 size 是 B x T x *。当 batch_first False…

umi搭建react项目

UMI 是一个基于 React 的可扩展企业级前端应用框架,提供路由、状态管理、构建和部署等功能,可以帮助开发者快速构建复杂的单页面应用(SPA)和多页面应用(MPA)。它与 React 的关系是,UMI 构建在 R…

0.0和0.00竟然不相等!!!BigDecimal别用错了比较方式

对于BigDecimal字段,可以使用compareTo()方法和equals()方法进行比较。但是要注意这两种方法的作用有所不同。一般都应该使用BigDecimal比较值,而不是使用经常用到的equals方法比较内容。 1.compareTo()方法 是用来比较两个BigDecimal对象的大小关系。…

出现dependencies.dependency.version‘ for xxxx:jar is missing的解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 出现如下问题:dependencies.dependency.version for xxxx:jar is missing. 且一直提示Pom文件缺失依赖包(由于公司项目,此处不放图) 2. 原理分析 这个错误通常发生在 Maven 项目中,表示在项目的依赖关系中找不到指定…

大数据知识点分享:Python的固定语法

Python编码声明 为源文件指定特定的字符编码,需要在py文件的首行或第二行插入一行特殊的注释行 #-*-coding:utf-8-*- 2.单行注释 单行注释以井号(#)开头 # 这是一个单独成行的注释 print(Hello, World!) # 这是一个在代码后面的注释 3…

移动端自动化测试工具 Appium 之 main 启动

文章目录 一、背景二、生成xml文件2.1、创建xml方法2.2、执行主类MainTest2.3、自动生成的xml2.4、工程目录2.5、执行结果 三、命令行执行appium服务四、主方法启动类五、集成Jenkins六、总结 一、背景 Jenkins 做集成测试是不错的工具,那么UI自动化是否可以&#…

图解自动驾驶中的运动规划(Motion Planning),附几十种规划算法

目录 1 自动驾驶驶向何处?2 什么是运动规划?3 运动规划实战教程4 加入我们5 订阅需知 1 自动驾驶驶向何处? 自动驾驶,又称无人驾驶,是依靠计算机与人工智能技术在没有人为操纵的情况下,完成完整、安全、有效…

2.1.2 事件驱动reactor的原理与实现

LINUX 精通 2 day14 20240513 day15 20240514 算法刷题:2维前缀和,一二维差分 耗时 135min 习题课 4h 课程补20240425 耗时:4h 课程链接地址 回顾 怎么学0voice课网络io——一请求一线程,一个client一个连接再accpet分配io f…

linux系统修改网卡名称

说明: 因操作过程需要停用网卡,导致ssh远程连接不上,需要控制台登录操作。 测试环境: CentOS7.9、8.2虚拟机 Suse15 SP4虚拟机 操作步骤: 方法一: 1、 查看网卡当前名称及状态 ip a2、 将网卡状态从启用…

记一次苹果appstore提审拒审问题1.2

有关苹果appstore审核1.2问题的处理方案 2023.8.6苹果回复 Bug Fix Submissions The issues weve identified below are eligible to be resolved on your next update. If this submission includes bug fixes and youd like to have it approved at this time, reply to thi…

Flutter 中的 CupertinoActionSheet 小部件:全面指南

Flutter 中的 CupertinoActionSheet 小部件:全面指南 在Flutter中,CupertinoActionSheet是用于在iOS风格的应用中显示动作面板的组件。它提供了一个简洁的界面,让用户可以快速从一组选项中做出选择。CupertinoActionSheet通常伴随着一个或多…

RK3566(泰山派):GP7101背光驱动

RK3566(泰山派):GP7101背光驱动 文章目录 RK3566(泰山派):GP7101背光驱动GP7101背光驱动电路配置i2c1设备树创建驱动编写Makefilegp7101_bl.c驱动触摸I2C驱动框架。驱动中的结构体probe函数devm_backlight_…

过滤器Filter和拦截器Interceptor实现登录校验

一.过滤器 Filter过滤器可以把对资源的请求拦截下来,从而实现一些登录验证的功能 1.Filter的快速入门 1.定义Filter:定义一个类,实现Filter接口,并重写其所有方法。2.配置 public class dofilter implements Filter {Override //初始化只…

【JAVA】数组的定义与使用

前一篇我们讲述了方法的使用和递归,这一讲 我们来叙述一下数组相关知识点。最近更新较快,大家紧跟步伐哦~~ 1. 数组的基本概念 1.1 为什么要使用数组 假设现在要存5个学生的javaSE考试成绩,并对其进行输出,按照之前掌握的知识点&…

obsidian 外观设置解毒

前言 一入obsidian深似海,外观设置也是五花八门,仿佛回到读书时期折腾桌面一样。 我对比了AnuPpuccin、minimal和其他的一些外观主题,设置都太复杂了,尤其是需要调整CSS文件,最后发现一款,非常好用&#…

数据传送指令

数据传送:负责把数据、地址或立即数传送到寄存器或存储单元中 数据传送指令可以分为四个类型:通用数据传送指令、地址传送指令、标志位传送指令、专用累加器传送指令(输入、输出指令) 一、通用数据传送指令 (一)传送字或字节指…

前端框架-echarts

Echarts 项目中要使用到echarts框架&#xff0c;从零开始在csdn上记笔记。 这是一个基础的代码&#xff0c;小白入门看一下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" co…

刷题之找到字符串所有字母异位词

找到字符串所有字母异位词 滑动窗口。滑动窗口大小为待比较数组的大小。 class Solution { public:vector<int> findAnagrams(string s, string p) {//滑动窗口vector<int>result;if(s.size()<p.size())return result;vector<int>pnum(26,0);//记录p的字…