Lua 面向对象 | 菜鸟教程


本站和网页 https://www.runoob.com/lua/lua-object-oriented.html 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

Lua 面向对象 | 菜鸟教程
菜鸟教程 -- 学的不仅是技术,更是梦想!
首页
HTML
CSS
JavaScript
Vue
Bootstrap
NodeJS
Python3
Python2
Java
C++
C#
Go
SQL
Linux
jQuery
本地书签
首页
HTML
CSS
JS
本地书签
Search
Python3 教程
Python2 教程
Vue3 教程
vue2 教程
Bootstrap3 教程
Bootstrap4 教程
Bootstrap5 教程
Bootstrap2 教程
Lua 教程
Lua 教程
Lua 环境安装
Lua 基本语法
Lua 数据类型
Lua 变量
Lua 循环
Lua 流程控制
Lua 函数
Lua 运算符
Lua 字符串
Lua 数组
Lua 迭代器
Lua table(表)
Lua 模块与包
Lua 元表(Metatable)
Lua 协同程序(coroutine)
Lua 文件 I/O
Lua 错误处理
Lua 调试(Debug)
Lua 垃圾回收
Lua 面向对象
Lua 数据库访问
Lua5.3 参考手册
Lua 垃圾回收
Lua 数据库访问
Lua 面向对象
面向对象编程(Object Oriented Programming,OOP)是一种非常流行的计算机编程架构。
以下几种编程语言都支持面向对象编程:
C++
Java
Objective-C
Smalltalk
C#
Ruby
面向对象特征
1) 封装:指能够把一个实体的信息、功能、响应都装入一个单独的对象中的特性。
2) 继承:继承的方法允许在不改动原程序的基础上对其进行扩充,这样使得原功能得以保存,而新功能也得以扩展。这有利于减少重复编码,提高软件的开发效率。
3) 多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
4)抽象:抽象(Abstraction)是简化复杂的现实问题的途径,它可以为具体问题找到最恰当的类定义,并且可以在最恰当的继承级别解释问题。
Lua 中面向对象
我们知道,对象由属性和方法组成。LUA中最基本的结构是table,所以需要用table来描述对象的属性。
lua 中的 function 可以用来表示方法。那么LUA中的类可以通过 table + function 模拟出来。至于继承,可以通过 metetable 模拟出来(不推荐用,只模拟最基本的对象大部分实现够用了)。
Lua 中的表不仅在某种意义上是一种对象。像对象一样,表也有状态(成员变量);也有与对象的值独立的本性,特别是拥有两个不同值的对象(table)代表两个不同的对象;一个对象在不同的时候也可以有不同的值,但他始终是一个对象;与对象类似,表的生命周期与其由什么创建、在哪创建没有关系。对象有他们的成员函数,表也有:
Account = {balance = 0}
function Account.withdraw (v)
Account.balance = Account.balance - v
end
这个定义创建了一个新的函数,并且保存在Account对象的withdraw域内,下面我们可以这样调用:
Account.withdraw(100.00)
一个简单实例
以下简单的类包含了三个属性: area, length 和 breadth,printArea方法用于打印计算结果:
实例
-- 元类
Rectangle = {area = 0, length = 0, breadth = 0}
-- 派生类的方法 new
function Rectangle:new (o,length,breadth)
o = o or {}
setmetatable(o, self)
self.__index = self
self.length = length or 0
self.breadth = breadth or 0
self.area = length*breadth;
return o
end
-- 派生类的方法 printArea
function Rectangle:printArea ()
print("矩形面积为 ",self.area)
end
创建对象
创建对象是为类的实例分配内存的过程。每个类都有属于自己的内存并共享公共数据。
r = Rectangle:new(nil,10,20)
访问属性
我们可以使用点号(.)来访问类的属性:
print(r.length)
访问成员函数
我们可以使用冒号 : 来访问类的成员函数:
r:printArea()
内存在对象初始化时分配。
完整实例
以下我们演示了 Lua 面向对象的完整实例:
实例
-- 元类
Shape = {area = 0}
-- 基础类方法 new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- 基础类方法 printArea
function Shape:printArea ()
print("面积为 ",self.area)
end
-- 创建对象
myshape = Shape:new(nil,10)
myshape:printArea()
执行以上程序,输出结果为:
面积为 100
Lua 继承
继承是指一个对象直接使用另一对象的属性和方法。可用于扩展基础类的属性和方法。
以下演示了一个简单的继承实例:
-- Meta class
Shape = {area = 0}
-- 基础类方法 new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- 基础类方法 printArea
function Shape:printArea ()
print("面积为 ",self.area)
end
接下来的实例,Square 对象继承了 Shape 类:
Square = Shape:new()
-- Derived class method new
function Square:new (o,side)
o = o or Shape:new(o,side)
setmetatable(o, self)
self.__index = self
return o
end
完整实例
以下实例我们继承了一个简单的类,来扩展派生类的方法,派生类中保留了继承类的成员变量和方法:
实例
-- Meta class
Shape = {area = 0}
-- 基础类方法 new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- 基础类方法 printArea
function Shape:printArea ()
print("面积为 ",self.area)
end
-- 创建对象
myshape = Shape:new(nil,10)
myshape:printArea()
Square = Shape:new()
-- 派生类方法 new
function Square:new (o,side)
o = o or Shape:new(o,side)
setmetatable(o, self)
self.__index = self
return o
end
-- 派生类方法 printArea
function Square:printArea ()
print("正方形面积为 ",self.area)
end
-- 创建对象
mysquare = Square:new(nil,10)
mysquare:printArea()
Rectangle = Shape:new()
-- 派生类方法 new
function Rectangle:new (o,length,breadth)
o = o or Shape:new(o)
setmetatable(o, self)
self.__index = self
self.area = length * breadth
return o
end
-- 派生类方法 printArea
function Rectangle:printArea ()
print("矩形面积为 ",self.area)
end
-- 创建对象
myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()
执行以上代码,输出结果为:
面积为 100
正方形面积为 100
矩形面积为 200
函数重写
Lua 中我们可以重写基础类的函数,在派生类中定义自己的实现方式:
-- 派生类方法 printArea
function Square:printArea ()
print("正方形面积 ",self.area)
end
Lua 垃圾回收
Lua 数据库访问
9 篇笔记
写笔记
#0 达也酱 jja***@163.com 43按实例的写法,每次new新实例的时候都需要将第一个变量的值设为nil,很不方便。
可以稍做变形,把变量o放在函数里创建,免去麻烦。
--创建一个类,表示四边形
local RectAngle = { length, width, area} --声明类名和类成员变量
function RectAngle: new (len,wid) --声明新建实例的New方法
local o = {
--设定各个项的值
length = len or 0,
width = wid or 0,
area =len*wid
setmetatable(o,{__index = self} )--将自身的表映射到新new出来的表中
return o
end
function RectAngle:getInfo()--获取表内信息的方法
return self.length,self.width,self.area
end
a = RectAngle:new(10,20)
print(a:getInfo()) -- 输出:10 20 200
b = RectAngle:new(10,10)
print(b:getInfo()) -- 输出:10 10 100
print(a:getInfo()) -- 输出:10 20 200达也酱 达也酱 jja***@163.com5年前 (2017-11-10)
#0 gray.yang gra***ang@fibocom.com 23补充: . 与 : 的区别在于使用 : 定义的函数隐含 self 参数,使用 : 调用函数会自动传入 table 至 self 参数,示例:
classA={}
function classA:getob(name)
print(self)
ob={}
setmetatable(ob,self)
self.__index=self
self.name=name
return ob
end
function classA:getself()
return self
end
c1=classA:getob("A")
c2=classA:getob("B")
print(string.rep("*",30))
print(c1:getself())
print(c2:getself())
print(string.rep("*",30))
----------------------继承------------------------
classB=classA:getob() ----非常重要,用于获取继承的self
function classB:getob(name,address)
ob=classA:getob(name)
setmetatable(ob,self)
self.__index=self
self.address=address
return ob
end
c3=classB:getob("gray.yang","shenzhen")
print(c3:getself())
输出结果:
table: 0x7fc99d404c80
table: 0x7fc99d404c80
******************************
table: 0x7fc99d402c50
table: 0x7fc99d404cc0
******************************
table: 0x7fc99d404c80
table: 0x7fc99d404c80
table: 0x7fc99d405640gray.yang gray.yang gra***ang@fibocom.com5年前 (2018-04-11)
#0 miaosu5cm mia***5cm@163.com 6模拟类和继承
classA={}
function classA.new(cls,...) --定义类方法时使用"."号,不适用隐式传参
this={}
setmetatable(this,cls)
cls.__index=cls --将元表的__index设为自身,访问表的属性不存在时会搜索元表
cls.init(this,...) --初始化表,注意访问类的方法都是".",此时不会隐式传入参数
return this
end
function classA.init(self,name)
self.name=name
end
function classA.getname(self)
return self.name
end
p=classA:new("gray.yang")
print(p:getname())
print(string.rep("*",50))
模拟继承
classB=classA:new() --获得实例
function classB.new(cls,...)
this={}
setmetatable(this,cls)
cls.__index=cls
cls.init(this,...)
return this
end
function classB.init(self,name,address)
super=getmetatable(self)
super:init(name) --使用父类初始化
self.address=address
end
function classB.getaddress(self)
return self.address
end
b=classB:new("tom.li","shenzhen")
print("getbname==============>",b:getname())
print("getbaddress===========>",b:getaddress())miaosu5cm miaosu5cm mia***5cm@163.com5年前 (2018-06-28)
#0 Ives 571***385@qq.com 2多重继承
-- 在table 'plist'中查找'k'
local function search(k, plist)
for i = 1, #plist do
local v = plist[i][k] -- 尝试第i个基类
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, c)
return o
end
return c -- 返回新类
end
-- 类Named
Named = {}
function Named:getname()
return self.name
end
function Named:setname(n)
self.name = n
end
-- 类Account
Account = {balance = 0}
function Account:withdraw(w)
self.balance = self.balance - v
end
-- 创建一个新类NamedAccount,同时从Account和Named派生
NamedAccount = createClass(Account, Named)
account = NamedAccount:new()
account:setname("Ives")
print(account:getname()) -- 输出 IvesIves Ives 571***385@qq.com5年前 (2018-07-15)
#0 大轩 tol***uan@163.com 参考地址 7一个简单的面向对象实现
--[[
Lua 中使用":"实现面向对象方式的调用。":"只是语法糖,它同时在方法的声明与实现中增加了一个
名为 self 的隐藏参数,这个参数就是对象本身。
]]
--实例:
Account = {balance = 0};
--生成对象
function Account:new(o)
o = o or {}; --如果用户没有提供对象,则创建一个。
setmetatable(o, self); --将 Account 作为新创建的对象元表
self.__index = self; --将新对象元表的 __index 指向为 Account(这样新对象就可以通过索引来访问 Account 的值了)
return o; --将新对象返回
end
--存款
function Account:deposit(v)
self.balance = self.balance + v;
end
--取款
function Account:withdraw(v)
self.balance = self.balance - v;
end
--查询
function Account:demand()
print(self.balance);
end
--创建对象
myAccount = Account:new();
--通过索引访问
print(myAccount.balance);
--调用函数
myAccount:deposit(100);
myAccount:withdraw(50);
myAccount:demand();
执行结果:
50
[Finished in 0.0s]大轩 大轩 tol***uan@163.com 参考地址4年前 (2018-08-08)
#0 wildwolf wil***lf12@qq.com 1其中 A 为抽象类,B 为矩形类,C 为立方体类。
C 继承 B,B 继承 A。
类对象各自独立,不影响类默认成员属性值。
B = {length, width, area}
function B:new(len,wid)
local A = {length=0,width=0}
local o = {}
setmetatable(o,A)
B.__index=A
o.length=len or A.length
o.width=wid or A.width
o.area=o.length*o.width
return o
end
a=B:new(2,3)
b=B:new(3,4)
print("长方形a的面积为"..a.area)
print("长方形b的面积为"..b.area)
print("长方形a的面积仍然为"..a.area..", a与b独立存在")
c=B:new()
print("长方形c根据默认构造函数的面积为"..c.area..", c的长宽分别为",c.length,c.width)
--立方体C,继承长方形类B
C = {high=0, volume=0, rectangle=B.new()} --增加体积值和高度
C.__index=C
function C:new(len, wid, hig)
local o={}
setmetatable(o,C) --将原始类C作为它对象的原表
o.rectangle=B:new(len,wid)
o.high=hig or C.high
o.volume=o.high*o.rectangle.area
return o
end
cubeA=C:new(2,3,4)
cubeB=C:new(3,4,5)
print("立方体A的体积为"..cubeA.volume)
print("立方体B的体积为"..cubeB.volume)
print("立方体A的体积仍然为"..cubeA.volume..", A与B独立存在")
print("立方体A底面长方体的长与宽分别为"
,cubeA.rectangle.length
,cubeA.rectangle.width)
print("立方体B底面长方体的长与宽分别为"
,cubeB.rectangle.length
,cubeB.rectangle.width)
print("cubeA和cubeB的底边长方形同样独立存在")wildwolf wildwolf wil***lf12@qq.com4年前 (2019-02-28)
#0 小糊涂仙 128***0653@qq.com 7我的实测结果与作者的理论有出入,先创建多个对象,然后再依次输出,会发现结果都是最后一个对象的值。
Rectangle 的封装:
Rectangle = {area = 0, length = 0, breadth = 0}
function Rectangle:new (o,length,breadth)
o = o or {}
setmetatable(o, self)
self.__index = self
self.length = length or 0
self.breadth = breadth or 0
self.area = length*breadth;
return o
end
function Rectangle:printArea ()
print("矩形面积为 ",self.area)
end
-- 创建
local r = Rectangle:new(nil, 2, 3);
local p = Rectangle:new(nil, 4, 5);
-- 输出
r:printArea();
p:printArea();
结果:
矩形面积为 20
矩形面积为 20
也就是说,p 和 r 其实不是两个完全无关的对象。小糊涂仙 小糊涂仙 128***0653@qq.com4年前 (2019-04-15)
#0 sgjz1973 163***2445@qq.com 7回楼上,两个新建实例并没有关系,只是新建实例时修改了元表,第二次新建覆盖了值:
local Rect = {area = 0,length = 0,windth = 0};
function Rect:new(length,windth)
local t = {};
setmetatable(t,self);
self.__index = self;
t.length = length;
t.windth = windth;
t.area = t.length * t.windth;
return t;
end
function Rect:ShowArea()
print(self.area);
end
local a = Rect:new(1,2);
local b = Rect:new(3,4);
a:ShowArea();
b:ShowArea();
print(a);
print(b);
输出结果:
12
table: 0000000019AA22A0
table: 0000000019AA2610sgjz1973 sgjz1973 163***2445@qq.com4年前 (2019-04-25)
#0 dalige 459***786@qq.com 6对楼上补充说明:
Rect 作为 new 出来的表(楼上代码写的 a 和 b)的元表:由于没有设置 __newindex 元方法。所以 a 和 b 在赋值的时候把长和宽的值赋给了自己,并没有把值赋给 Rect (也就是说 Rect 表中的数据一直都没有改变过)。
a 和 b 在调用 ShowArea 方法的时候,自己的表里没有这个方法,会到元表中寻找这个方法,元表(Rect)中设置了 __index 元方法,所以能找到 ShowArea 这个方法,然后调用。(注意这里是 a 和 b 调用的 ShowArea 方法,所以 ShowArea 方法中 self 指向的是 a 和 b,而不是 Rect)。dalige dalige 459***786@qq.com3年前 (2020-06-23)
点我分享笔记
取消
分享笔记
昵称昵称 (必填)
邮箱邮箱 (必填)
引用地址引用地址
分类导航
HTML / CSSHTML 教程HTML5 教程CSS 教程CSS3 教程Bootstrap3 教程Bootstrap4 教程Bootstrap5 教程Font Awesome 教程Foundation 教程 JavaScriptJavaScript 教程HTML DOM 教程jQuery 教程AngularJS 教程AngularJS2 教程Vue.js 教程Vue3 教程React 教程TypeScript 教程jQuery UI 教程jQuery EasyUI 教程Node.js 教程AJAX 教程JSON 教程Echarts 教程Chart.js 教程Highcharts 教程Google 地图 教程 服务端Python 教程Python2.x 教程Linux 教程Docker 教程Ruby 教程Java 教程C 教程C++ 教程Perl 教程Servlet 教程JSP 教程Lua 教程Rust 教程Scala 教程Go 教程PHP 教程数据结构与算法Django 教程Zookeeper 教程设计模式正则表达式Maven 教程Verilog 教程ASP 教程AppML 教程VBScript 教程 数据库SQL 教程MySQL 教程PostgreSQL 教程SQLite 教程MongoDB 教程Redis 教程Memcached 教程 数据分析Python 教程NumPy 教程Pandas 教程Matplotlib 教程Scipy 教程R 教程Julia 教程 移动端Android 教程Swift 教程jQuery Mobile 教程ionic 教程Kotlin 教程 XML 教程XML 教程DTD 教程XML DOM 教程XSLT 教程XPath 教程XQuery 教程XLink 教程XPointer 教程XML Schema 教程XSL-FO 教程SVG 教程 ASP.NETASP.NET 教程C# 教程Web Pages 教程Razor 教程MVC 教程Web Forms 教程 Web ServiceWeb Service 教程WSDL 教程SOAP 教程RSS 教程RDF 教程 开发工具Eclipse 教程Git 教程Svn 教程Markdown 教程 网站建设HTTP 教程网站建设指南浏览器信息网站主机教程TCP/IP 教程W3C 教程网站品质
Advertisement
反馈/建议
在线实例
·HTML 实例
·CSS 实例
·JavaScript 实例
·Ajax 实例
·jQuery 实例
·XML 实例
·Java 实例
字符集&工具
· HTML 字符集设置
· HTML ASCII 字符集
· JS 混淆/加密
· PNG/JPEG 图片压缩
· HTML 拾色器
· JSON 格式化工具
· 随机数生成器
最新更新
·
Go fmt.Printf ...
·
CSS backdrop-filte
·
使用 JS 的 down...
·
Navigator produ...
·
Navigator onLin...
·
Navigator langu...
·
Navigator geolo...
站点信息
·
意见反馈
·
免责声明
·
关于我们
·
文章归档
关注微信
Copyright 2013-2022 菜鸟教程
runoob.com All Rights Reserved. 备案号:闽ICP备15012807号-1
微信关注