Lua面向对象编程
一、面向对象特征
封装:指能够把一个实体的信息、功能、响应都装入一个单独的对象中的特性
继承:继承的思路允许在不改变源程序的基础上对其进行扩充 使得原功能得以保存,新功能得以扩展
多态:同一操作作用于不同的对象 可以有不同的解释 产生不同的执行结果 在运行时 可以通过基类的指针来调用实现派生类的方法
抽象:简化复杂的显示问题的途径 可以为具体问题找到最恰当的类定义 可以在最恰当的继承级别解释问题
二、面向对象简单实现
1.对象由属性和方法组成 lua用table来描述对象的属性 用function描述对象的方法
2.继承则可以通过元表模仿
3.lua中的表也有状态 --- 不同的成员变量
--全局对象版
Windows1 = {width = 100, height = 200 }
function Windows1.setWidth(width)
Windows1.width = Windows1.width + width
end
function Windows1.setheight(height)
Windows1.height = Windows1.height + height
end
Windows1.setWidth(50)
Windows1.setheight(50)
print(Windows1.width)
print(Windows1.height)
缺点:
创建名为Windows1的对象 并且设置了一个方法 setWidth(width) setheight(height)
缺点 对象Role是以全局变量的方式创建的 会有一种“全局污染”的威胁
全局污染:变量Role在其他地方被重新赋值(例如赋值为nil) 对象里的属性或者方法会面临被销毁或不能正常工作的情况
解决方法:提供一种“接受者”的解决方法 额外添加一个参数self来表示对象本身
第二版:提供接受者版 缺点 需要手动传入self 将点号用冒号代替
Windows2 = {width = 100, height = 200 }
function Windows2.setWidth(self, width)
Windows2.width = self.width + width
end
function Windows2.setHeight(self, height)
Windows2.height = self.height + height
end
w = Windows2
w.setWidth(w, 200)
w.setHeight(w, 400)
print(Windows2.width)
print(Windows2.height)
优雅的第三版 原理:在函数定义时 使用冒号函数内部会有隐藏的self
--优雅的第三版
Windows3 = {width = 100, height = 200 }
function Windows3:setWidth(width)
Windows3.width = self.width + width
end
function Windows3:setHeight(height)
Windows3.height = self.height + height
end
w = Windows3
w:setWidth(200)
w:setHeight(400)
print(Windows3.width)
print(Windows3.height)
其中 w.setWidth (w, 300) 就等价于w:setWidth(300) 原理 函数调用时 使用冒号会默认传入一个参数(调用者自身)self
三、lua实现类机制
类实现原理 :通过表table 元表metatable 元方法metamethod 封装一个类
--Base原型表 用来描述一个类 在原型表中填写类方法 类属性则声明在狗子哦啊函数的新表中
Base = {}
--实例化对象时 创建一个新表 将新标的元表设置为 原型表
function Base.new(self)
--创建新表 并且声明自己的属性信息 即就是成员变量
local ntable = {x = 0, y = 0}
--将新表的元表设置为原型表
setmetatable(ntable, Base)
self. __index = self
return ntable
end
--函数定义时 使用点号 内部不存在self 所以需要手动传入
function Base.setXY(self, x, y)
self.x = x
self.y = y
end
function Base.printXY(self)
print("x = "..self.x)
print("y = "..self.y)
end
local object1 = Base:new()
--函数调用时 使用冒号 会自动传入一个调用者自身的参数 刚好是我们想要的结果
object1:setXY(199, 200)
object1:printXY()
--未调用设置方法 即为查看默认属性
local object2 = Base:new()
object2:printXY()