lua 面向对象
对象的特点是:
对象拥有自己的数据,两个对象即使数据完全相同,他们也是相互独立的;
对象之间可以共享对象的行为,也就是他们的方法是一致的;
lua中的table就非常适合作为一个对象,可以在table中方便的定义属性和方法:
Point = { x = 0, y = 0 }
Point.set = function (x, y)
Point.x = x
Point.y = y
end
Point.set(1, 2)
但是要符合面相对象的规则,方法可以操作不同的对象,而不是同一个特定对象,我们可以将需要操作的对象作为参数传入:
Point = {}
Point.set = function (pt, x, y)
pt.x = x
pt.y = y
end
local pt1 = { x = 0, y = 0 }
Point.set(pt, 1, 2)
我们可以将所有方法定义在一个集合中,然后在调用的时候将第一个参数作为对象传入即可。不过传统的面向对象是可以隐藏对象这个参数,而直接使用this代替,lua也提供了一种类似的操作,就是“:”操作符:
Point = {}
function Point:set (x, y) // 等价于 function Point.set(self, x, y)
self.x = x
self.y = y
end
Point:set(1, 2) // 等价于Point.set(Point, 1, 2)
这里冒号操作符的作用就是省略了第一个参数self,self是代表冒号之前的那个对象。.操作符和:操作符是可以随意互换的,只要在调用的时候确定参数的正确性即可,因为冒号操作符并没有引入新的东西,只是一种“语法糖”而已。
类是创建对象的模版,同一个类型的所有对象都具有相同的行为。
在lua中,如何创建一个类?lua中使用table来创建一个类,然后所有实例的元表都可以设置为这个类,即相同类型的对象具有相同的元表:
创建一个Point类:
Point = {}
function Point.new (x, y)
local instance = {} // 创建一个实例
setmetatable(instance, Point) // 设置所有实例的元表都是Point,所以实例的方法都会去Point中查找
Point.__index = Point // 同时必须设置__index元方法为Point,因为实例的所有方法,我们都会定义在Point中
instance.x = x
instance.y = y
return instance
end
添加类的方法:
function Point:set (x, y)
self.x = x
self.y = y
end
function Point:get ()
return {x, y}
end
使用:
local pt = Point.new(1, 2)
pt:set(3, 4)
local data = pt:get()
类的继承:根据lua的table特性,如果一个字段在table中不存在,那么lua回去尝试调用元表的__index元方法,如果元方法是一个table,那么该规则会持续下去,直到找到一个定义或者搜索结束。这种机制就类似一个链式结构,这个链式结构就形成了一个继承关系。子类不存在某个方法的时候,总是会向父类去寻找,依次类推。
从Point类继承一个子类Point3D:
Point3D = {}
function Point3D:new (x, y, z)
local instance = Point:new(x, y) // 创建一个父类对象,继承了父类所有的属性
instance.z = z
setmetatable(Point3D, Point) // 设置子类Point3D的元表为父类Point
Point3D.__index = Point3D // 设置元方法为自己
setmetatable(instance. Point3D) // 设置instance的元表为Point3D
return instance
end
重写父类的方法:
function Point3D:set (x, y, z)
Point.set(self, x, y)
self.z = z
end
实现自己的方法:
function Point3D:setZ (z)
self.z = z
end
甚至为instace实现特有的方法:
function instance:print()
print("it is a printer for instance ", self)
end
使用:
local pt3d = Point3D:new(1, 2, 3)
pt3d:set(4, 5, 6)
pt3d:setZ(10)
pt3d:print()
这样实现后,就形成了instance -> Point3D -> Point 的链式结构,lua会按照这个顺序依此搜索方法,调用最先找到的方法。
实例:
Point.lua
--#! /usr/local/bin/lua
Point = {}
Point.__index = Point;
local POINT_PROPS = {
x = ,
y =
}
function Point:new(x, y)
local instance = {}
for k, v in pairs(POINT_PROPS) do
instance[k] = v
end
instance.x = x
instance.y = y
setmetatable(instance, Point)
return instance
end
function Point:set (x, y)
print("Point set x:"..x.." y:"..y)
self.x = x
self.y = y
end
function Point.get (self)
print("Point get x:"..self.x.." y:"..self.y)
return {x, y}
end
Point3D.lua
--#! /usr/local/bin/lua
require "Point"
Point3D = {}
Point3D.__index = Point3D;
local POINT3D_PROPS = {
z =
}
function Point3D:new (x, y, z)
local instance = Point:new(x, y)
for k, v in pairs(POINT3D_PROPS) do
instance[k] = v
end
instance.z = z
setmetatable(Point3D, Point)
setmetatable(instance, Point3D)
return instance
end
function Point3D:set (x, y, z)
print("Point3D set x:"..x.." y:"..y.." z:"..z)
Point.set(self, x, y)
self.z = z
end
function Point3D:setZ (z)
print("Point3D setZ z:"..z)
self.z = z
end
function Point3D:get ()
print("Point3D get x:"..self.x.." y:"..self.y.." z:"..self.z)
end
test.lua
require "Point3D" local pt = Point3D:new(, , );
for k, v in pairs(pt) do
print(k, v)
end
pt:set(, , )
pt:get() function pt:print()
print("pt", self.x, self.y, self.z, self)
end pt:print()
多重继承:
为了实现多重继承,就无法为对象设置一个父类作为元表,必须将多个父类保存起来,然后设置一个元方法__index为函数,在函数调用的时候,在多个父类中为对象寻找适合的方法。
Color.lua
Color = {}
function Color:setColor (r, g, b, a)
self.r = r
self.g = g
self.b = b
self.a = a
end
function Color:getColor ()
print("color r:"..self.r.." g:"..self.g.." b:"..self.b.." a"..self.a)
return {self.r, self.g, self.b, self.a}
end
test.lua
require "Point"
require "Color" ColorPoint = {}
ColorPoint.__interfaces = { Point, Color }
ColorPoint.__index = function (t, key)
local interfaces = ColorPoint.__interfaces; for i = , #interfaces do
local func = interfaces[i][key]
if func then return func end
end
return nil
end function ColorPoint:new ()
local instance = {}
setmetatable(instance, ColorPoint)
return instance
end local cp = ColorPoint:new()
local cp1 = ColorPoint:new() cp:set(, )
cp:get()
cp:setColor(, , , )
cp:getColor()
单列模式,利用了闭包的原理,将数据隐蔽起来:
local _instance = {}
local filelist = {}
local fileCount =
local isExist = function (filename)
return not (filelist[filename] == nil)
end
function _instance:load (filename)
if (isExist(filename)) then print(filename) return end
local file = io.open(filename)
if (file) then
io.input(file)
local data = assert(io.read("*all"))
filelist[filename] = data
fileCount = fileCount +
io.close(file)
else
error("FileManager load file "..filename.." failed")
end
end
function _instance:getFileCount ()
return fileCount
end
function _instance:getFileData (filename)
return filelist[filename]
end
function _instance:removeFileData (filename)
if (filelist[filename]) then
filelist[filename] = nil
fileCount = fileCount -
end
assert(fileCount >= , "FileManager removeFileData file count error")
end
function _instance:isExist (filename)
return not (filelist[filename] == nil)
end
FileManager = {
getInstance = function()
return _instance
end
}
_G["FileManager"] = FileManager
return FileManager
FileManager:getInstance():load("1.txt")
FileManager:getInstance():load("2.txt")
print(FileManager:getInstance():getFileCount())
print(FileManager:getInstance():getFileData("1.txt"))
FileManager:getInstance():removeFileData("1.txt")
print(FileManager:getInstance():getFileCount())
print(FileManager:getInstance():getFileData("1.txt"))
print(FileManager:getInstance():getFileData("2.txt")
lua 面向对象的更多相关文章
- Lua面向对象----类、继承、多继承、单例的实现
(本文转载)学习之用,侵权立删! 原文地址 http://blog.csdn.net/y_23k_bug/article/details/19965877?utm_source=tuicool&a ...
- Lua面向对象之三:其它一些尝试
1.尝试一:子类对象调用被覆盖了的父类函数 根据元表设置流程,我们只有将父类元表找到就能调用父类的方法了 ①在子类Circle中增加一个调用父类方法的函数 --调用父类被子类覆盖了的name方法 fu ...
- Lua面向对象之二:类继承
1.类继承 ①代码 Sharp = { } --① 父类 function Sharp:new() local new_sharp = { } self.__index = self --②,self ...
- Lua面向对象之一:简单例子
1.Lua面向对象实现步骤 ①创建一个全局表(称之为元表) ②设置这个元表的__index值(值通常为元表自己,这样就能通过__index查找到对应的属性和方法) __index 赋值其实是一个fun ...
- lua面向对象封装
lua面向对象的一个封装,直接贴代码 --swfclass = {};local cs = {};function _class( child, base, ... )-- _.s( child ...
- lua面向对象实现(实例化对象、继承、多态、多继承、单例模式)
lua面向对象实现: 一个类就像是一个创建对象的模具.有些面向对象语言提供了类的概念,在这些语言中每个对象都是某个特定类的实例.lua则没有类的概念,每个对象只能自定义行为和形态.不过,要在lua中模 ...
- Step By Step(Lua面向对象)
Step By Step(Lua面向对象) Lua中的table就是一种对象,但是如果直接使用仍然会存在大量的问题,见如下代码: 1 Account = {balance = 0}2 function ...
- Lua面向对象
lua中的table就是一种对象,但是如果直接使用仍然会存在大量的问题,如下: 1 Account = {balance = 0}2 function Account.withdraw(v)3 Acc ...
- Lua面向对象设计
首先对于Lua语言,它没有打算被用来进行大型的程序设计,相反,Lua目标定于小型到中型的程序设计,通常是作为大型系统的一部分,所以它只提供了一套精简的元素,很多高级语言的概念都没有.这样Lua就成为了 ...
随机推荐
- Jmeter—8 连接microsoft sql server数据库取数据
本文以Jmeter 连接microsoft sql server为例. 1 从微软官网下载Microsoft SQL Server JDBC Driver 地址:http://www.microsof ...
- jvm1
字节码常量池: 01开头的说明是一个utf-8编码的常量,那么后面就一定要跟两个字节也就是四位16进制的数,来表示这个常量占几个字节,然后后面再跟与这个字节数对应长度的utf-8编码的字符串.之所以一 ...
- php大力力 [043节] 现在要做个删除前的提示功能
php大力力 [043节] 现在要做个删除前的提示功能
- HDU 5234 DP背包
题意:给一个n*m的矩阵,每个点是一个蛋糕的的重量,然后小明只能向右,向下走,求在不超过K千克的情况下,小明最终能吃得最大重量的蛋糕. 思路:类似背包DP: 状态转移方程:dp[i][j][k]--- ...
- Qt开发环境中使用报表控件FastReport遇到的一些问题(一)
FastReport是一款优秀的报表控件,由俄罗斯开发,国内有代理商.Qt环境下可实现报表功能的还有一款叫NCReport,也是收费控件,比较来比较去还是觉得前者功能强点.网上讲解此控件在Qt中使用的 ...
- WebDriver定位元素方法
如果把页面上的元素看作人的话,在现实世界如何找到某人呢?方法有三: 一.通过人本身的属性,例如他的姓名,手机号,身份证号,性别,这些可区别他人的属性.在web页面上的元素也有这些属性,例如,id.na ...
- Eclipse Java 调试基本技巧
前言 这一部分是Eclipse中最为重要的部分.调试的重要性想必大家都清楚. 调试无疑是做项目最苦比的事情,但优秀的编码习惯,良好的调试方式能让这没那么苦,甚至还有点乐趣:). 本文讲解使用Eclip ...
- 基于MVC4+EasyUI的Web开发框架形成之旅--框架总体界面介绍
在前面介绍了一些关于最新基于MVC4+EasyUI的Web开发框架文章,虽然Web开发框架的相关技术文章会随着技术的探讨一直写下去,不过这个系列的文章,到这里做一个总结,展示一下整体基于MVC4+Ea ...
- android四大组件之ContentProvider(二)
ContentProvider学习笔记 上一章节我们编写了自定义的一个StudentProvider,他提供了两种供外界访问数据的方式,content://come.demo.sqlite.stude ...
- [MySql] - 开启外部访问
打开 mysql 的查询窗口(使用root),使用SQL: -- 使用mysql库 use mysql; -- 更新密码 update user set password=PASSWORD('xxxx ...