睬脲的Lua系列
文章目录Lua 教程设计目的Lua 特性Lua 应用场景第一个 Lua 程序Lua 教程轻量小巧的脚本语言用标准C编写并以源代码形式开放里约热内卢天主教大学研究小组93年设计目的为了嵌入应用程序中从而为应用程序提供灵活扩展和定制功能Lua 特性轻量级:用标准C编写并以源代码形式开放编译后仅仅一百余K可方便的嵌入别的程序可扩展: Lua提供易于使用的扩展接口和机制由宿主语言(通常C或C++)提供这些
文章目录
Lua 流程控制
- 控制结构的条件表达式结果可以是任何值,
- false和nil为假,
- true和非nil为真。
- 0 为 true:
--[ 0 为 true ]
if(0)
then
print("0 为 true")
end
a = 100;
if( a < 20 or nil)
then
print("a 小于 20" )
else
print("a 大于 20" )
end
print("a 的值为 :", a)
a = 100
if( a == 10 and 0)
then
print("a 的值为 10" )
elseif( a == 20 and 0)
then
print("a 的值为 20" )
elseif( a == 30 and 0)
then
print("a 的值为 30" )
else
print("没有匹配 a 的值" )
end
print("a 的真实值为: ", a )
没有匹配 a 的值
a 的真实值为: 100
Lua 面向对象
- OOP)是一种非常流行的计算机编程架构。
- 以下几种编程语言都支持面向对象编程:
C++
Java
Objective-C
Smalltalk
C#
Ruby
面向对象特征
- 1)
- 封装:把实体信息、功能、响应都装入一个单独的对象中的特性
- 2) 继承
- 继承的方法允许在不改动原程序的基础上对其扩充,
- 使原功能保存,而新功能也扩展
- 有利于减少重复编码
- 3) 多态:
- 同一操作作用于不同的对象,
- 可有不同的解释,
- 产生不同的执行结果。
- 在运行时,可通过指向基类的指针,来调用实现派生类中的方法
- 4)抽象:
- 简化复杂的现实问题的途径
- 它可以为具体问题找到最恰当的类定义,
- 且可以在最恰当的继承级别解释问题。
Lua 中面向对象
- 对象由属性和方法组成。
- LUA中最基本的结构table,要用table来描述对象的属性
- lua 中function 可用来表示方法。
- LUA中的类可以通过 table + function 模拟出来。
- 继承,可通过 metetable 模拟(不推用,只模拟最基本的对象大部分时间够用)。
- Lua 中表不仅在某种意义上是一种对象。
- 像对象一样,表也有状态(成员变量);
也有与对象的值独立的本性,特别是拥有两个不同值的对象(table)代表两个不同的对象; - 一个对象在不同的时候也可以有不同的值,但他始终是一个对象;
- 与对象类似,表的生命周期与其由什么创建、在哪创建没有关系。
- 表也有成员函数
Account = {balance = 0}
function Account.withdraw (v)
Account.balance = Account.balance - v
end
Account.withdraw(100.00)
print(Account.balance)
- 答案是-100
- 创建一个新的函数,保存在Account对象的withdraw域内,
- 这样调用
- Account.withdraw(100.00)
实例
- 以下类含三个属性:
- area, length 和 breadth,
- printArea方法用于打印计算结果:
-- 元类
Rectangle = {area = 0, length = 0, breadth = 0}
-- 派生类的方法 new
function Rectangle:new (o,length,breadth)
o = o or {}
setmetatable(o, self)
self.__index = self
self.length = length or 0
self.breadth = breadth or 0
self.area = length*breadth;
return o
end
-- 派生类的方法 printArea
function Rectangle:printArea ()
print("矩形面积为 ",self.area)
end
canci
Lua 元表(Metatable)
- table中可访问对应的key来得value
- 但无法对两个table操作
- Lua 提供元表
- 允许我们改变table行为
- 每个行为关联对应的元方法
- 用元表我们可定义计算两个table的相加a+b
- 当Lua对两个表相加时
- 先检查两者之一是否有元表
- 之后检查是否有"__add"字段
- 若找到,则调对应值
- "__add"等即时字段
- 其对应的值(往往一个函数或是table)就是"元方法"
- setmetatable(table,metatable):
- 对指定 table 设置元表(metatable),
- 如果元表(metatable)中存在 __metatable 键值,setmetatable失败
- getmetatable(table): 返回对象的元表(metatable)
- 如何对指定的表设置元表
mytable = {} -- 普通表
mymetatable = {} -- 元表
setmetatable(mytable,mymetatable) -- 把 mymetatable 设为 mytable 的元表
- 以上也可直接写成一行:
mytable = setmetatable({},{})
- 以下为返回对象元表:
getmetatable(mytable) -- 这回返回mymetatable
把元表设置成普通表的元素!
__index 元方法
- metatable 最常用键
- 通过键来访问 table时,
- 如果这个键没值,
- Lua就会寻找该table的metatable(假定有metatable)中的__index 键
说的非常有道理!
- 如果__index含一个表格,Lua会在表格中查找相应的键。
other是个table啊!t也是个table啊!!
other = { foo = 3 }
t = setmetatable({}, { __index = other })
t.foo
3
t.bar
nil
意思就是t.foo找不到,就找里面的metatable,看看这个metatable有没有__index键,__index含一个表other,进去找foo
other = { foo = 3 }
t = setmetatable({aa=123}, { __index = other})
print(t.aa)
- __index含一个函数的话,Lua就调那个函数,
- table和键会作为参数传递给函数
- __index 元方法看表中元素是否存在,
- 如果不存在,返回nil;
- 如果存在则由 __index 返回结果。
mytable = setmetatable({key1 = "value1"}, {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return nil
end
end
})
print(mytable.key1,mytable.key2)
- 结果为:
value1 metatablevalue
- mytable表赋值为 {key1 = “value1”}。
- mytable 设置了元表,元方法__index
- mytable中查key1,找到,返该元素,找不到继续
- mytable表中找key2,如果找到
- 返metatablevalue,找不到继续
- 判断元表有没有__index方法,如果__index方法是一个函数,则调用该函数
- 元方法中查看是否传入 “key2” 键的参数(mytable.key2已设置),如果传入 “key2” 参数返回 “metatablevalue”,否则返回 mytable 对应的键值
mytable = setmetatable({key1 = "value1"}, { __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)
总结
- Lua 查找一个表元素时的规则,就是如下3步:
- 在表中查找,如果找到,返回该元素,找不到则继续
- 判断该表是否有元表,如果没有,返nil,有元表则继续
- 元表有没有 __index 方法,
- __index 方法为 nil,返nil;
- __index是表,则重复 1、2、3;
- __index 是函数,则返回该函数的返回值
__newindex 元方法
- 用来对表更新,__index则对表访问
- 当你给表的一个缺少的索引赋值,
- 解释器就查找__newindex 元方法:
- 存在则调用这个函数而不进行赋值
mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })
print(mytable.key1)
mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)
value1
nil 新值2
新值1 nil
- 表设置元方法__newindex,在对新索引键newkey赋值时(mytable.newkey = “新值2”),会调元方法,而不赋值
- 如果对已存在的索引键key1,则会赋值,而不调元方法 __newindex。
canci
Lua table
- 帮助创建不同的数据类型
- 数组、字典
- Lua table 用关联型数组
- 可用任意类型的值作数组索引
- 但不能是 nil
- 不固定大小,可扩容
- 也是通过table来解决
- 模块(module)、包(package)和对象(Object)的
- string.format表示使用"format"来索引table string
table(表)的构造
- 构造器是创建和初始化表的表达式。
- 表是Lua特有的功能强大的东西。
- 最简单的构造函数是{},用来创建一个空表。可以直接初始化数组:
-- 初始化表
mytable = {}
-- 指定值
mytable[1]= "Lua"
-- 移除引用
mytable = nil
-- lua 垃圾回收会释放内存
- 为 table a 并设元素
- 将a赋给b
- 则a与b都指向同一内存。
- a 设为 nil ,则 b 同样能访问 table 的元素。
- 如果没有指定的变量指向a,Lua的垃圾回收机制会清理相对应的内存。
canci
Lua 模块与包
- 模块类似一个封装库
- 5.1 开始,Lua 加入标准的模块管理机制
- 把一些公用的代码放在一个文件里
- 以 API 接口的形式在其他地方调
- 代码的重用和降低代码耦合度
- Lua 模块由
- 变量、
- 函数
- 等已知元素组成的 table
- 创建一个模块很简单,就是创建一个 table
- 然后把需要导出的常量、函数放入其中
- 最后返回这个 table
- 创建自定义模块 module.lua
-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}
-- 定义一个常量
module.constant = "这是一个常量"
-- 定义一个函数
function module.func1()
io.write("这是一个公有函数!\n")
end
local function func2()
print("这是一个私有函数!")
end
function module.func3()
func2()
end
return module
- 模块结构就是一个table结构
- 可像操作调用table里的元素那样来操作调用模块里的常量或函数
- func2为程序块局部变量
- 私有函数
- 必须通过模块里的公有函数来调
require 函数
- require的函数用来加载模块
require("<模块名>")
或
require “<模块名>”
canci
C/C++嵌入Lua
-
Lua是一门嵌入式语言,
- 其他应用可以链接它,从而将它作为一个库,
- 以便使用它的所有特性。
-
OS X环境下,如何在C/C++代码中嵌入Lua。
编译库文件
- 已完成lua库文件的编译过程,并生成了静态库 liblua.a:
创建C++控制台应用程序;
添加头文件搜索路径;
添加lua库文件liblua.a;
输出Hello World
canci
初始化Lua环境
- “如何在OS X中,初始化Lua开发环境”。
- 适用于初学者,尤其是带着这样的疑惑的读者:“我想学习Lua语言,用它作为编程语言,来进行项目开发,该如何配置开发环境?”
- Lua官网 http://www.lua.org/download.html
- 上下载最新的lua-5.3.4.tar.gz
- 解压到指定文件夹,这里设置为:
/Users/huaxingzheng/develop
/Users/huaxingzheng/develop/lua-5.3.4
cd lua-5.3.4
make macosx test
- 安装成功后,屏幕会输出
Lua 5.3.4 Copyright (C) 1994-2017 Lua.org, PUC-Rio
- 现为lua添加查找路径,打开Terminal,
- 粘贴运行以下内容
# Add environment variable LUA_ROOT for Lua5.3.4
export LUA_ROOT=/Users/huaxingzheng/develop/lua-5.3.4/src
export PATH=$LUA_ROOT:$PATH
- OK!,你可以在任意位置调用 lua
cacni
Lua 函数
-
Lua 提供许多的内建函数,你可以很方便的在程序中调用它们,如print()函数可以将传入的参数打印在控制台上。
-
Lua 函数主要两用途:
-
1.完成指定的任务,这种情况下函数作为调用语句使用;
-
2.计算并返回值,这种情况下函数作为赋值语句的表达式使用。
Lua 函数定义格式如下:
optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)
function_body
return result_params_comma_separated
end
- optional_function_scope:
- 可选的制定函数是全局函数还是局部函数,
- 未设置该参数默认为全局函数,
- 如果你需要设置函数为局部函数需要使用关键字 local。
- result_params_comma_separated:
- 函数返回值,
- 可以返回多个值,每个值以逗号隔开。
canci
Lua 教程
- 轻量小巧的脚本语言
- 用标准C编写并以源代码形式开放
- 里约热内卢天主教大学研究小组93年
设计目的
- 为了嵌入应用程序中
- 从而为应用程序提供灵活扩展和定制功能
Lua 特性
- 轻量级:
- 用标准C编写并以源代码形式开放
- 编译后仅仅一百余K
- 可方便的嵌入别的程序
- 可扩展: Lua提供易于使用的扩展接口和机制
- 由宿主语言(通常C或C++)提供这些功能,Lua可用它们
- 就像是本来就内置的功能
- 其它:
- 支持面向过程编程和函数式编程
- 自动内存管理
- 只提供一种通用类型的表
- 用它可实现数组,哈希表,集合,对象
- 语言内置模式匹配;闭包;函数也可以看做一个值;提供多线程(协同进程,并非操作系统所支持的线程)支持;
- 通过闭包和table可方便支持面向对象编程所需要的一些关键机制,
- 数据抽象,虚函数,继承和重载等
Lua 应用场景
- 游戏开发
- 独立应用脚本
- Web 应用脚本
- 扩展和数据库插件如:MySQL Proxy 和 MySQL WorkBench
- 安全系统,如入侵检测系统
第一个 Lua 程序
print(“Hello World!”)
Lua 基本语法
交互式编程
- 交互式编程模式lua -i 或 lua 来启用
$ lua -i
$ Lua 5.3.0 Copyright (C) 1994-2015 Lua.org, PUC-Rio
- 命令行中输入:
print(“Hello World!”)
- 按下回车键,输出结果
脚本式编程
- 代码保存到一个以 lua 结尾的文件,并执行
- 将如下代码存储在名为 hello.lua 的脚本文件
print("Hello World!")
print("www.runoob.com")
$ lua hello.lua
Hello World!
www.runoob.com
- 我们也可以将代码修改为如下形式
#!/usr/local/bin/lua
print("Hello World!")
print("www.runoob.com")
- 指定了 Lua 的解释器 /usr/local/bin directory。
- # 号标记解释器会忽略它。
- 接下来我们为脚本添加可执行权限,并执行:
./hello.lua
Hello World!
www.runoob.com
注释
- 两个减号是单行注释:
- 多行注释
--[[
多行注释
多行注释
--]]
标示符
- 标示符用于定义一个变量,函数获取其他用户定义的项。
- 以一个字母或下划线 _ 开头后加上0个或多个字母,下划线,数
- 不要用下划线加大写字母的标示符,因为Lua的保留字也是这样的。
- 不允许用如 @, $, 和 % 来定义标示符。
- 区分大小写
- 一些正确的标示符:
mohd zara abc move_name a_123
myname50 _temp j a23b9 retVal
关键词
- 以下列出Lua 的保留关键字。
- 保留关键字不能作为常量或变量或其他用户自定义标示符:
and break do else elseif end false for
function if in local nil not or repeat
return then true until while goto
- 一般约定
- 下划线开头连接一串大写字母的名字(_VERSION)被保留
- Lua 内部全局变量
全局变量
- 默认变量总认为是全局
- 全局变量不需声明,给一个变量赋值后即创建了这个全局变量,访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil。
> print(b)
nil
> b=10
> print(b)
10
>
- 如果你想删一个全局变量,只需要将变量赋值为nil。
b = nil
print(b) --> nil - 变量b就好像从没被使用过一样。
- 当且仅当一个变量不等于nil时,这个变量即存在。
canci
Lua 数据类型
- Lua是动态类型语言,变量不要类型定义,只需要为变量赋值。
- 值可存在变量中,作为参数传递或结果返回
- 8 个基本类型:
- nil、boolean、number、
- string、userdata、function、
- thread 和 table
- nil最简单,只有值nil属于该类,
- 一个无效值(条件表达式中相当于false)。
- boolean含两个值:false和true。
- number
- 双精度类型的实浮点数
- string
- 一对双引号或单引号来表示
- function
- C 或 Lua 编写的函数
- userdata
- 任意存储在变量中的C数据结构
比如你lua_pushlightuserdata一个指针进入lua里面,你在lua里面用type查看这个变量,他就是userdata类型的
- thread
- 执行的独立线路,用于执行协同程序
- Lua 中的表(table)其实是一个"关联数组
- 索引可以是数字、字符串或表类型。
- Lua 里,table的创建是通过"构造表达式"完成,
- 最简单构造表达式是{},用来创建一个空表。
print(type("Hello world")) --> string
print(type(10.4*3)) --> number
print(type(print)) --> function
print(type(type)) --> function
print(type(true)) --> boolean
print(type(nil)) --> nil
print(type(type(X))) --> string
和你没完!
canci
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)