Lua 面向对象基础-类和对象(一)


lua是一门面向过程的脚本语言,lua语言对于事物、结构通通描述为 table,而类和对象作为面向对象语言的核心,在lua中也是通过table 这一结构来模仿和描述;table 这一结构本身即可描述对象,即实例,而类的定义在lua中需要table来仿造

1. lua中创建对象

在如java的面向对象语言中,一般使用class 来定义类,再根据类的定义实例化一个对象,而在lua中,首先引出的是对象,

a ={name = "xxx"}

如此 a作为一个变量,也即为一个实例化的对象,该对象有一个字段name,值为xxx。

2.lua中定义类的思路

为了定义一个类型,首先需要用一个对象来描述该类型的公共属性,这个对象可以称为元类,用table来描述,如

a = {name = "name_a"}

对象a用来作为最顶级的父类,从该对象产生其他的子类对象,即是派生的过程,在lua中,通过将a这个元类的各个字段进行类似值拷贝的操作,来产生新的子对象

3.元表的概念

元表本身即是一个table,可以通过setmetatable(table_a,table_b)的调用,来将table_b设置为table_a的元表,设置元表的过程即:

a = {name = "name_a"}
b = {age = 1}
setmetatable(a,b)
--设置后--
a = {__metatable = b}

a的默认字段__metatable将从nil 赋值为 b,b作为一个table,会包含另外一个默认的字段 __index 字段,称为元方法,此时的a实际为

b = {__index = nil, male = 1 }
a = {__metatable = b }
--此处只是表示实际a的字段,设置元表不可这样直接赋值,需要setmetatable(a,b)

同时lua规定

对于一个table未知字段的访问,如果该字段不存在,会查找该字段的元表中的元方法,如元方法为function函数,返回该函数的结果,如元方法仍为一个table,即在该table中查找该字段,重复上述步骤

,那么此时如果访问a对象的age字段,将返回table b的 __index字段值,此时该字段为nil,因此可以将b的__index字段赋值一个table,那么对于a的未知字段的访问,即会在b的__index 的table中查找,如

a = {}
c = {age = 1}
b = {__index = c ,male = 1}
setmetatable(a,b)
print("a.age=",a.age)
--打印 a.age=	1

更加巧妙的是,你可以只用2个table完成上面的功能,即将b的__index字段复赋值为b本身,那么,对于a的未知字段的访问,即会在b中进行查找

a = {}
b = {age =1,male =1 }
b.__index =b
setmetatable(a,b)
print("a.age=",a.age)
--打印 a.age=	1

如此,a的字段即可理解为从b继承而来,那么a可以是b的一个实例对象,借助这个核心思想,即可将b对象作为类的定义,b的字段描述了这一类对象的公共行为和属性,a对象通过元类和元方法访问到b的属性和行为,那么可以定义一个类似java的new方法,来通过table b,产生table a对象,来实现从类的定义 实例化对象

4.类的定义和实例化
--基类account的定义
account = { name = function()
    print("account")
end,
age = 10 
}

function account:new(o)
    local o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
end

specialAcc = account:new() --实例化一个对象

function:new()中的 :相当于将调用函数的对象作为隐藏参数传入,在函数中可以用self来访问该对象,该函数意为定义account对象的 new字段为一个function

根据之前所说的思路,这里new方法中创建一个新的table并返回,来作为实例化的过程,并将传入的self对象(即account对象)设置为新对象的元表,将self(即account对象)的元方法设置为account对象自身,来达到新对象o访问到基类对象account的字段,调用 specialAcc = account:new() 即可实例化一个对象,它可以访问到account的所有属性,那么account对象即为类的定义

5. 重写类的方法
function specialAcc:name()
    print("special account ", self.age)

end

sp = specialAcc:new()
sp:name()

可以重新定义子类对象继承的基类方法,那么对于specialAcc.name 的方法,将返回重写后的结果,并且同时specialAcc对象也成为新的派生类,可调用他从account 对象继承来的new方法 来实例化一个对象 sp,而sp对于name方法的访问,将返回specialAcc.name 的结果,sp对象也可以称为新的派生类,也同时作为实例化的对象,在lua的面向过程下模拟出的面向对象,可以更灵活的实现封装、继承和多态的思想。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值