一、Lua的基本数据类型:
1.数值(number):内部以double表示.
2.字符串(string):总是以零结尾,但可以包含任意字符(包括零),因此并不等价于C字符串,
而是其超集.
3.布尔(boolean):只有"true"和"false"两个值.
4.函数(function):Lua的关键概念之一.不简单等同于C的函数或函数指针.
5.表(table):异构的Hash表.Lua的关键概念之一.
6.userdata:用户(非脚本用户)定义的C数据结构.脚本用户只能使用它,不能定义.
7.线程(thread):Lua协作线程(coroutine),与一般操作系统的抢占式线程不一样.
8.nil:代表什么也没有,可以与C的NULL类比,但它不是空指针.
总结:
LUA逻辑中常用的类型:number,string,boolean, nil
LUA面向对象设计:Table, function
LUA多线程的概念:协程
LUA与其他语言耦合:userdata,LUA可以调用C语言,LUA底层是C实现,是C实现的一种
解释性语言,在效率上基本上没区别。
二、LUA元表
lua里的所有数据结构都是表。metatable可以改变table的行为。例如加法行为,
table本身没有加法行为。可以通过修改元表中的__add域,来提供表的加法行为。
__add叫做元方法(metamethod),一个表默认是不带元表的。getmetatable可以获取元表。
(1)元表的定义
t = {}
print(getmetatable(t)) --nil
setmetatable可以设置元表。
t = {}
setmetatable(t, t) --设置自己是自己的元表
print(t == getmetatable(t)) --true
任何一个表可以其他表的元表。一个表也可以是自己的元表。
定义二:
mytable = {} -- 普通表
mymetatable = {} -- 元表
setmetatable(mytable,mymetatable) -- 把 mymetatable 设为 mytable 的元表
定义三:
mytable = setmetatable({},{})
(2)__index 元方法:面向对象(继承)主要的依据
a:通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的
metatable(假定有metatable)中的__index键。如果__index包含一个表格,
Lua会在表格中查找相应的键。
b:__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。
(3)__newindex 元方法
a:__newindex 元方法用来对表更新,__index则用来对表访问 。
当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:
如果存在则调用这个函数而不进行赋值操作。
(4)其他元方法:__add,__sub,__mul,__div等。
(5)_call(a, ...) --执行方法调用,把一个表当方法使用。
(6)__tostring(a) --字符串输出,修改输出行为
三、LUA中面向对象
(1)面向对象的几个特性:封装,继承,多态,抽象
(2)对象由属性和方法组成。LUA中最基本的结构是table,所以需要用table来描述
对象的属性。lua中的function可以用来表示方法。那么LUA中的类可以通过
table + function模拟出来。
(3)继承,可以通过metetable模拟出来。
(4)对象案例
Cal = {}
function Cal:New(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Cal:Add(a, b)
print("Cal Add")
return a + b
end
a = Cal:New() --返回一个以Cal为父类的对象
print(a:Add(5, 6)) --11 ,--a中没有Add,会去Cal中查找并调用
(5)继承案例
Cal = {}
function Cal:New(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Cal:Add(a, b)
print("Cal Add")
return a + b
end
SubCal = Cal:New() --定义一个Cal的子类SubCal
function SubCal:Add(a, b) --覆写了父类的方法
print("SubCal Add")
return a + b
end
a = SubCal:New()
print(a:Add(5, 6)) --11 --调用子类的方法
(6)根据cocos给出的一个class实现,可以更方便的在lua中定义类,ctor是定义,new是
调用时使用的语句,下面是案例:
//定义名为 Shape 的基础类
local Shape = class("Shape")
//ctor() 是类的构造函数,在调用 Shape.new() 创建 Shape 对象实例时会自动执行
function Shape:ctor(shapeName)
self.shapeName = shapeName
printf("Shape:ctor(%s)", self.shapeName)
end
//为 Shape 定义个名为 draw() 的方法
function Shape:draw()
printf("draw %s", self.shapeName)
end
// Circle 是 Shape 的继承类
local Circle = class("Circle", Shape)
function Circle:ctor()
-- 如果继承类覆盖了 ctor() 构造函数,那么必须手动调用父类构造函数
-- 类名.super 可以访问指定类的父类
Circle.super.ctor(self, "circle")
self.radius = 100
end
function Circle:setRadius(radius)
self.radius = radius
end
// 覆盖父类的同名方法
function Circle:draw()
printf("draw %s, raidus = %0.2f", self.shapeName, self.raidus)
end
--
local Rectangle = class("Rectangle", Shape)
function Rectangle:ctor()
Rectangle.super.ctor(self, "rectangle")
end
local circle = Circle.new() -- 输出: Shape:ctor(circle)
circle:setRaidus(200)
circle:draw() -- 输出: draw circle, radius = 200.00
local rectangle = Rectangle.new() -- 输出: Shape:ctor(rectangle)
rectangle:draw() -- 输出: draw rectangle
四、LUA函数用法
(1)将函数当作一条语句;当作表达式
print(8*9, 9/8) --> 72 1.125
a = math.sin(3) + math.cos(10) --> a = -0.69795152101659
print(os.date()) --> Sat Mar 9 12:14:08 2013
(2)函数调用:如果是字符串或者是表时可以省掉()
print "Hello World" <==> print("Hello World")
dofile 'a.lua' <==> dofile('a.lua')
print[[a multi-line <==> print([[a multi-line
message]] message]])
f{x=10, y=20} <==> f({x=10, y=20})
type{} <==> type({})
(3)Lua支持面向对象,操作符为冒号‘:’。o:foo(x) <==> o.foo(o, x)
(4)Lua可以处理多传参数的情况,多传参数将被丢弃。
(5)不同于常规函数,Lua的函数可以返回多个返回值。
x,y = foo2() -- x="a", y="b"
x,y = foo0() -- x=nil, y=nil
慎用括号来强制返回值个数为一个:print((foo2())) --> a
(6)在Lua中,function跟其他值一样,也是匿名的。function被作为一个值存储在变量中
a = {p = print}
a.p("Hello World") --> Hello World
(7)创建函数的表达式:
function foo (x) return 2*x end
--实际上为:
foo = function (x) return 2*x end
(8)全局函数与非全局函数
写法一:
Lib = {}
Lib.foo = function (x,y) return x + y end
Lib.goo = function (x,y) return x - y end
写法二:
Lib = {}
function Lib.foo (x,y) return x + y end
function Lib.goo (x,y) return x - y end
写法三:面向对象写法
local Animal = {}
function Animal:Eat( food )
print("Animal:Eat", self, food)
end
function Animal.Sleep( time )
print("Animal.Sleep", self, time)
end
总结:在Eat(冒号函数)内部有一个参数self,在Sleep(点函数)内部没有参数self;
调用:用冒号(:)调用函数时,会默认传一个值(调用者自身)作为第一个参数;
用点(.)调用函数时,则没有;
function Animal:Eat( food ) end <--> function Animal.Eat( self, food ) end
(9)闭合函数,特殊的“非局部变量”
function count()
local i = 0;
return function()
i = i + 1;
return i;
end
end
(10)尾调用避免堆栈溢出:测试用例 print(foo(99999))
function foo(n)
if n > 0 then
return foo(n - 1); //如果改成foo(n - 1)+1就会溢出,不属于尾调用
else
return "end";
end
end
1.数值(number):内部以double表示.
2.字符串(string):总是以零结尾,但可以包含任意字符(包括零),因此并不等价于C字符串,
而是其超集.
3.布尔(boolean):只有"true"和"false"两个值.
4.函数(function):Lua的关键概念之一.不简单等同于C的函数或函数指针.
5.表(table):异构的Hash表.Lua的关键概念之一.
6.userdata:用户(非脚本用户)定义的C数据结构.脚本用户只能使用它,不能定义.
7.线程(thread):Lua协作线程(coroutine),与一般操作系统的抢占式线程不一样.
8.nil:代表什么也没有,可以与C的NULL类比,但它不是空指针.
总结:
LUA逻辑中常用的类型:number,string,boolean, nil
LUA面向对象设计:Table, function
LUA多线程的概念:协程
LUA与其他语言耦合:userdata,LUA可以调用C语言,LUA底层是C实现,是C实现的一种
解释性语言,在效率上基本上没区别。
二、LUA元表
lua里的所有数据结构都是表。metatable可以改变table的行为。例如加法行为,
table本身没有加法行为。可以通过修改元表中的__add域,来提供表的加法行为。
__add叫做元方法(metamethod),一个表默认是不带元表的。getmetatable可以获取元表。
(1)元表的定义
t = {}
print(getmetatable(t)) --nil
setmetatable可以设置元表。
t = {}
setmetatable(t, t) --设置自己是自己的元表
print(t == getmetatable(t)) --true
任何一个表可以其他表的元表。一个表也可以是自己的元表。
定义二:
mytable = {} -- 普通表
mymetatable = {} -- 元表
setmetatable(mytable,mymetatable) -- 把 mymetatable 设为 mytable 的元表
定义三:
mytable = setmetatable({},{})
(2)__index 元方法:面向对象(继承)主要的依据
a:通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的
metatable(假定有metatable)中的__index键。如果__index包含一个表格,
Lua会在表格中查找相应的键。
b:__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。
(3)__newindex 元方法
a:__newindex 元方法用来对表更新,__index则用来对表访问 。
当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:
如果存在则调用这个函数而不进行赋值操作。
(4)其他元方法:__add,__sub,__mul,__div等。
(5)_call(a, ...) --执行方法调用,把一个表当方法使用。
(6)__tostring(a) --字符串输出,修改输出行为
三、LUA中面向对象
(1)面向对象的几个特性:封装,继承,多态,抽象
(2)对象由属性和方法组成。LUA中最基本的结构是table,所以需要用table来描述
对象的属性。lua中的function可以用来表示方法。那么LUA中的类可以通过
table + function模拟出来。
(3)继承,可以通过metetable模拟出来。
(4)对象案例
Cal = {}
function Cal:New(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Cal:Add(a, b)
print("Cal Add")
return a + b
end
a = Cal:New() --返回一个以Cal为父类的对象
print(a:Add(5, 6)) --11 ,--a中没有Add,会去Cal中查找并调用
(5)继承案例
Cal = {}
function Cal:New(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Cal:Add(a, b)
print("Cal Add")
return a + b
end
SubCal = Cal:New() --定义一个Cal的子类SubCal
function SubCal:Add(a, b) --覆写了父类的方法
print("SubCal Add")
return a + b
end
a = SubCal:New()
print(a:Add(5, 6)) --11 --调用子类的方法
(6)根据cocos给出的一个class实现,可以更方便的在lua中定义类,ctor是定义,new是
调用时使用的语句,下面是案例:
//定义名为 Shape 的基础类
local Shape = class("Shape")
//ctor() 是类的构造函数,在调用 Shape.new() 创建 Shape 对象实例时会自动执行
function Shape:ctor(shapeName)
self.shapeName = shapeName
printf("Shape:ctor(%s)", self.shapeName)
end
//为 Shape 定义个名为 draw() 的方法
function Shape:draw()
printf("draw %s", self.shapeName)
end
// Circle 是 Shape 的继承类
local Circle = class("Circle", Shape)
function Circle:ctor()
-- 如果继承类覆盖了 ctor() 构造函数,那么必须手动调用父类构造函数
-- 类名.super 可以访问指定类的父类
Circle.super.ctor(self, "circle")
self.radius = 100
end
function Circle:setRadius(radius)
self.radius = radius
end
// 覆盖父类的同名方法
function Circle:draw()
printf("draw %s, raidus = %0.2f", self.shapeName, self.raidus)
end
--
local Rectangle = class("Rectangle", Shape)
function Rectangle:ctor()
Rectangle.super.ctor(self, "rectangle")
end
local circle = Circle.new() -- 输出: Shape:ctor(circle)
circle:setRaidus(200)
circle:draw() -- 输出: draw circle, radius = 200.00
local rectangle = Rectangle.new() -- 输出: Shape:ctor(rectangle)
rectangle:draw() -- 输出: draw rectangle
四、LUA函数用法
(1)将函数当作一条语句;当作表达式
print(8*9, 9/8) --> 72 1.125
a = math.sin(3) + math.cos(10) --> a = -0.69795152101659
print(os.date()) --> Sat Mar 9 12:14:08 2013
(2)函数调用:如果是字符串或者是表时可以省掉()
print "Hello World" <==> print("Hello World")
dofile 'a.lua' <==> dofile('a.lua')
print[[a multi-line <==> print([[a multi-line
message]] message]])
f{x=10, y=20} <==> f({x=10, y=20})
type{} <==> type({})
(3)Lua支持面向对象,操作符为冒号‘:’。o:foo(x) <==> o.foo(o, x)
(4)Lua可以处理多传参数的情况,多传参数将被丢弃。
(5)不同于常规函数,Lua的函数可以返回多个返回值。
x,y = foo2() -- x="a", y="b"
x,y = foo0() -- x=nil, y=nil
慎用括号来强制返回值个数为一个:print((foo2())) --> a
(6)在Lua中,function跟其他值一样,也是匿名的。function被作为一个值存储在变量中
a = {p = print}
a.p("Hello World") --> Hello World
(7)创建函数的表达式:
function foo (x) return 2*x end
--实际上为:
foo = function (x) return 2*x end
(8)全局函数与非全局函数
写法一:
Lib = {}
Lib.foo = function (x,y) return x + y end
Lib.goo = function (x,y) return x - y end
写法二:
Lib = {}
function Lib.foo (x,y) return x + y end
function Lib.goo (x,y) return x - y end
写法三:面向对象写法
local Animal = {}
function Animal:Eat( food )
print("Animal:Eat", self, food)
end
function Animal.Sleep( time )
print("Animal.Sleep", self, time)
end
总结:在Eat(冒号函数)内部有一个参数self,在Sleep(点函数)内部没有参数self;
调用:用冒号(:)调用函数时,会默认传一个值(调用者自身)作为第一个参数;
用点(.)调用函数时,则没有;
function Animal:Eat( food ) end <--> function Animal.Eat( self, food ) end
(9)闭合函数,特殊的“非局部变量”
function count()
local i = 0;
return function()
i = i + 1;
return i;
end
end
(10)尾调用避免堆栈溢出:测试用例 print(foo(99999))
function foo(n)
if n > 0 then
return foo(n - 1); //如果改成foo(n - 1)+1就会溢出,不属于尾调用
else
return "end";
end
end