LUA语法《二》

一、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







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值