请人做游戏的网站,上海网站制作案例,郑州网站建设亻汉狮网络,淮南网站推广概述 开发环境搭建 Lua语法 1.第一个Lua程序 2.变量 print(******变量*******);
--lua当中的简单变量类型
-- nil number string boolean
-- lua 中所有的变量声明 都不需要声明变量类型 它会自动的判断类型
-- 类似C# 中的var
--lua中的一个变量 可以随便赋值 ——…概述 开发环境搭建 Lua语法 1.第一个Lua程序 2.变量 print(******变量*******);
--lua当中的简单变量类型
-- nil number string boolean
-- lua 中所有的变量声明 都不需要声明变量类型 它会自动的判断类型
-- 类似C# 中的var
--lua中的一个变量 可以随便赋值 —— 自动识别类型--通过type 函数 我们可以得到变量的类型
-- type 的返回值是 string--lua中使用没有声明过的变量
--不会保错 默认值 是nil
print(b)--nil 有点类似 C#中的null
print(******nil*******);
a nil
print(a)
print(type(a))
print(type(type(a)))--number 所有的数据都是number
print(*******number*******)
a 1
print(a)
a 1.2
print(a)
print(type(a))print(*******string*******)
a 123
print(a);
print(type(a))
--字符串的声明使用单引号或者双引号包裹
--lua里 没有char
a 123
print(a)
print(type(a))print(*******boolean*******)
a true
print(a)
a false
print(a)
print(type(a))--复杂数据类型
--函数 function
--表 table
--数据结构 userdata
--协同程序 thread(线程)3.字符串操作 print(******字符串*******)
str 双引号字符串
str 单引号字符串--获取字符串的长度
print(*******字符串长度**********)
s Sun木兮
--一个汉字占3个长度
--英文符号 占1个长度
print(#s)print(*******字符串多行打印*******)
--方式一
--lua中也是支持转义字符的
print(123\n123)--方式二
s [[山有
木兮
木有
枝]]
print(s)
print([[心悦
君兮君]])print(*******字符串拼接*******)
--方式一
--字符串拼接 通过..
print(123 .. 456)
s1 111
s2 222
print(s1 .. s2)
s1 111
s2 222
print(s1 .. s2)--方式二
print(string.format(山有木兮 木%d, 67))
--%d: 与数字拼接
--%a: 与任何字符串拼接
--%s: 与字符串配对
--...print(*******别的类型转字符串*******)
a true;
print(tostring(a))print(*******字符串提供的公共方法*******)
str abCdeFg
--小写转大写的方法
--该方法不会改变原字符串之后返回一个新字符串 (string大部分都不会改变原字符串)
print(string.upper(str))
print(str)
--大写转小写
print(string.lower(str))
--翻转字符串
print(string.reverse(str))
--字符串索引查找
print(string.find(str, Cde)) --3 5
print(string.find(str, C)) -- 3 3
--截取字符串
print(string.sub(str, 3)) --CdeFg
print(string.sub(str, 3, 4)) --重载方法
--重复字符串
print(string.rep(str, 1)) --返回的是原字符串
print(string.rep(str, 2)) --abCdeFgabCdeFg 返回两遍字符串
--字符串修改
print(string.gsub(str, Cd, **)) -- 返回 ab**eFg 1 1代表修改的次数
str abCdeFgCd
print(string.gsub(str, Cd, **)) -- 返回 ab**eFg** 2--字符转 ASCII码
a string.byte(Lua, 1) --将字符串里的一个指定位置转为ASCII码
print(a)
--ASCII码 转字符
print(string.char(a)) 4.运算符 print(*******运算符********)print(*******算术运算符********)
-- 只有 - * / % ^(幂运算)
-- 没有自增自减 --
-- 没有复合运算符 - / * %
-- 字符串 可以进行 算数运算符操作 会自动转成 number--加法
print(加法运算 .. 1 2)
a 1
b 2
print(a b)
print(123 1) -- 输出124
print(123.4 1) -- 输出124.4--减法
print(减法运算 .. 1 - 2) -- 输出 -1
print(123.4 - 1) -- 输出 122.4--乘法
print(乘法运算 .. 1 * 2)
print(123.4 * 2) -- 246.8--除法
print(除法运算 .. 1 / 2) -- 0.5
print(123.4 / 2) -- 61.7--取余
print(取余运算 .. 1 % 2) -- 1
print(123.4 % 2) -- 1.4--幂运算
-- ^ 在lua中 该符号是幂运算 而在C#中^是异或
print(幂运算 .. 2 ^ 5)
print(123.4 ^ 2)print(*******条件运算符********)
-- ~(不等于C#中是!)
print(31)
print(31)
print(31)
print(31)
print(31)
print(3~1)print(*******逻辑运算符********)
-- 逻辑与 C#中 逻辑或 C#中 || 取反 C#中 !
-- Lua中 与and 或or 非not 在lua中and、or也支持短路
print(true and false) -- false
print(true and true) -- tureprint(true or false) -- true
print(false or false) -- falseprint(not true) -- falseprint(********短路测试*********)
print(false and print(123)) -- 输出 false
print(true and print(123)) -- 输出 123 nilprint(*******位运算符********)
-- | lua中不支持位运算符 需要我们自己实现print(*******三目运算符********)
-- lua中也不支持三目运算符 5.条件分支语句 print(***********条件分支语句************)
a 9
-- if 条件 then...end
--单分支
if a 5 thenprint(124)
end--双分支
--if 条件 then...else...end
if a 5 thenprint(123)
elseprint(321)
end--多分支
--if 条件 then...elseif 条件 then...elseif 条件 then...else...end
if a 5 thenprint(123)
--lua中 elseif 一定是连着写的 否则会报错
elseif a 6 thenprint(6)
elseif a 7 thenprint(7)
elseif a 8 thenprint(8)
elseif a 9 thenprint(9)
elseprint(other)
end-- 组合条件的使用
if a 3 and a 9 thenprint(3到9之间)
end-- Lua中没有switch 需要的话可以自己实现
6.循环 7.函数 print(********函数*******)
--function 函数名()
--end--a function()
--endprint(********无参数无返回值*******)
-- F1() -- 不能在一个函数声明之前去调用它
function F1()print(Fi函数)
end
F1()-- 有点类似 C#中 委托和事件
F2 function()print(F2函数)
end
F2()print(********有参数*******)
function F3(a)print(a)
end
F3(1)
F3(123)
F3(true)
-- 如果你传入的参数 和函数参数个数不匹配
-- 它不会报错 只会补空nil 或者丢弃
F3()
F3(1,2,3)print(********有返回值*******)
function F4(a)return a, 123, true
end
-- 多返回值时 在前面声明多个变量来接即可
-- 如果变量不够 不影响 值会接取对应位置的返回值
-- 如果变量多了 也不影响 多出的直接赋值nil
temp, temp2, temp3 F4(1)
print(temp)
print(temp2)
print(temp3)print(********函数的类型*******)
-- 函数类型 就是 function
F5 function()print(123)
end
print(type(F5))print(********函数的重载*******)
--函数名相同 参数类型不同 或者参数个数不同
--luaz中 函数不支持重载
--默认调用的是最后一个申明的这个函数
function F6()print(F6_1)
end
function F6(str)print(str)
endF6() -- 输出 ilprint(********变长参数*******)
function F7(...)--变长参数使用 用一个表存起来 再用arg {...}for i 1,#arg doprint(arg[i])end
end
F7(1,123,true,4,5,6,7)print(********函数嵌套*******)
--function F8()
-- F9 function()
-- print(123)
-- end
-- return F9
--end-- 简洁写法
function F8()return function()print(123)end
endf9 F8()
f9()--Lua 中闭包的体现
function F9(x)--改变传入参数的生命周期return function(y)return x yend
endf10 F9(10)
print(f10(5)) 8.复杂数据类型 —— 表 print(*********复杂数据类型 table***********)
--所有的复杂类型都是table表print(*********数组***********)
a {1,2,3,4,1231,true,nil}
--lua中 索引从1开始
print(a[0]) -- 输出 nil 超出索引不会报错
print(a[1]) -- 输出 1
print(a[5])
print(a[6])
print(a[7])
--# 是通用的获取长度的关键字
--在打印长度的时候 空被忽略
--如果表中数组中某一位变成nil 会影响#获取的长度
print(#a) -- 输出 6 第7位是nil所以会被忽略
--a {1,2,nil,4,1231,true,nil}
--print(#a) -- 输出 2print(*********数组的遍历***********)
for i 1,#a doprint(a[i])
endprint(*********二维数组***********)
--注意 其实lua中是没有二维数组的概念的 只是我们用表体现出数组、二维数组、字典的特征
a {{1,2,3},{4,5,6}}
print(a[1][1]) -- 第一个表
print(a[1][2])
print(a[1][3])
print(a[2][1]) -- 第二个表
print(a[2][2])
print(a[2][3])print(*********二维数组的遍历***********)
for i 1,#a dob a[i]for j 1,#b doprint(b[j])end
endprint(*********自定义索引***********)
-- 不建议自定义索引
aa {[0] 1,2,3, [-1] 4,5}
print(aa[0])
print(aa[-1])
print(aa[1])
print(aa[2])
print(aa[3])
print(#aa) 9.迭代器遍历 10.复杂数据类型 —— 表 字典 print(*************复杂数据类型——表2*****************)
print(******字典*****)
print(******字典的申明*********)
--字典是由键值对构成
a {[name] Sunset, [age] 19, [1] 5}
--返回单个变量 用中括号填键 来访问
print(a[name])
print(a[age])
print(a[1])
--还可以类型 .成员变量 的形式得到值
print(a.name)
print(a.age)
-- 虽然可以通过成员变量的形式得到值 但是不能是数字
--print(a.1)
--字典修改
a[name] Sunrise
print(a[name])
print(a.name)
--字典新增
a[sex] false
print(a[sex])
print(a.sex)
--字典删除 其实就是置空
a.sex nil
print(a[sex])
print(a.sex)print(************字典的遍历***********)
--如果要模拟字典遍历 一定用 pairs
for k,v in pairs(a) doprint(k,v)
end
-- 可以只得键
for k in pairs(a) doprint(k)print(a[k])
endfor _,v in pairs(a) doprint(v)
endprint(**********类和结构体************)print(**********表的公共操作**********) 类 print(**********类和结构体************)--Lua中是默认没有面向对象的 需要我们自己来实现
-- 成员变量 成员函数...
Student {--年龄age 1,--性别sex true,--成长函数Up function()-- 这样写 这个age 和表中的age没有任何关系 它是一个全局变量--print(age) -- 会输出 nil 而没有输出 1--想要在表内部函数中 调用表本身的属性或者方法--一定要指定是谁的 所以要使用得 表名.属性 或者 表名.方法print(Student.age) -- 输出 1print(成长中)end,--学习函数Learn function(t)-- 第二种 能够在函数内部调用自己属性或者方法的 方法-- 把自己作为一个参数传进来 在内部访问print(t.sex)print(学习中)end
}--Lua中 .和冒号 的区别
Student.Learn(Student)
--冒号调用方法 会默认把调用者 作为第一个参数传入方法中
Student:Learn()--声明表过后 在表外去声明表有的变量和方法
Student.name Sunset
Student.Speak function()print(说话)
end
-- 函数的第三种申明方式
function Student:Speak2()--lua中 有一个关键字 self表示 默认传入的第一个参数print(self.name .. 说话2)
end
--C#中要使用类 实例化对象new 静态直接点
--Lua中的类的表现 更新是一个类中有很多 静态变量和函数
print(Student.age)
print(Student.name)
Student.Up()
Student.Speak()
Student:Speak2()
Student.Speak2(Student) 表的公共操作 print(**********表的公共操作**********)
--表中 table提供的一些公共方法的讲解t1 {{age 1, name 123}, {age 2, name 345}}t2 {name Sunset, sex true}print(********插入********)
--插入
print(#t1)
table.insert(t1, t2)
print(#t1)
print(t1[1]) -- 打印出的是地址
print(t1[2])
print(t1[3])
print(t1[3].sex)print(********删除********)
--删除指定元素
--remove方法 传表进去 会移除最后一个索引的内容
table.remove(t1)
print(#t1)
print(t1[1].name)
print(t1[2].name)
print(t1[3])--remove方法 传两个参数 第一个参数 是要移除内部的表
--第二个参数 是要移除内容的索引
table.remove(t1, 1)
print(t1[1].name)
print(#t1)print(********排序********)
t2 {5,3,7,4,1,2}
--传入要排序的表 默认 升序排序
table.sort(t2)
for _,v in pairs(t2) doprint(v)
end
print(********排序自定义升降********)
--传入两个参数 第一个是用于排序的表
--第二个是 排序规则函数
table.sort(t2, function(a,b) -- 降序if a b thenreturn trueend
end)
for _,v in pairs(t2) doprint(v)
endprint(**********拼接********) -- 了解即可
tb {123, 456, 789, 10}
--连接函数 用于拼接表中元素 返回值 是一个字符串 大部分只能拼接字符串
str table.concat(tb, ;)
print(str) 11.多Lua脚本执行 print(**************多脚本执行***********)
print(**************全局变量和本地变量***********)
--目前为止我们申明的变量都是 全局变量
a 1
b 123for i1,2 doc Sunset
end
print(c)--本地局部变量的关键字 local
for i1,2 dolocal d Sunsetprint(循环中的d..d)
end
print(d)fun function()tt 123123 --所以如果要让它是局部变量就要加 local
end
fun()
print(tt) -- 在没有执行fun() 之前 会返回nilfun()执行后就变全局变量了-- 只能在自己脚本用的变量
local tt2 666print(**************多脚本执行***********)
--关键字 require(脚本名) require(脚本名)
require(Test) -- 打印 Test测试 456
print(testA) -- 打印 123
print(testLocalA) -- 打印不出 另一个脚本的本地变量print(**************脚本卸载***********)
--如果是require加载执行的脚本 加载一次过后就不会再被执行
require(Test)
--package.loaded[脚本名]
--返回值是 boolean 意思是 该脚本是否被执行
print(package.loaded[Test])
--卸载已经执行过的脚本
package.loaded[Test] nil;
print(package.loaded[Test])
--require(Test)--require 执行一个脚本时 可以在脚本最后返回一个外部希望获取的内容
local testLA require(Test)
print(testLA)print(**************大G表***********)
-- _G 表是一个总表table它将我们申明的所有全局变量都存储在其中
for k,v in pairs(_G) doprint(k,v)
end
-- 本地变量 加了local的变量是不会存储到_G表中的 12.特殊用法 print(********特殊用法*********)print(********多变量赋值*********)
a,b,c 1,2,123
print(a)
print(b)
print(c)
--多变量赋值 如果后面的值不够 会自动补空
a,b,c 1,2
print(a)
print(b)
print(c)
--多变量赋值 如果后面的值多了 会自动省略
a,b,c 1,2,3,4,5
print(a)
print(b)
print(c)print(********多返回值*********)
function Test()return 10,20,30,40
end
--多返回值时 用几个变量接 就有几个值
--如果少了 就会少接几个 如果多了 就会自动补空
a,b,c Test()
print(a)
print(b)
print(c)a,b,c,d,e Test()
print(a)
print(b)
print(c)
print(d)
print(e)print(********and or*********)
-- 逻辑与 逻辑或
-- and or 他们不仅可以连接 boolean 任何东西都可以用来连接
-- 在lua中 只有 nil和false 才认为是假
-- “短路” —— 对于and来说 有假则假 对于or来说 有真则真
-- 所以 他们只需要判断 第一个 是否满足 如果满足就会停止计算了
print(1 and 2) -- 2
print(0 and 1) -- 1
print(nil and 1) -- nul
print(false and 2) -- false
print(true and 3) -- 3print(true or 1) -- true
print(false or 1) -- 1
print(nil or 2) -- 2
print(1 or 2) -- 1--Lua不支持三目运算符 但是我可以靠and or 模拟出三目运算符来
x 3
y 2
local res (x y) and x or y
print(res) 13.协程 print(**********协同程序************)print(**********协程的创建************)
-- 常用方式
--coroutine.create()
fun function()print(123)
end
co coroutine.create(fun)
--协程的本质是一个线程对象
print(co) -- 返回 thread 地址
print(type(co)) -- 返回类型 thread 线程--coroutine.wrap()
co2 coroutine.wrap(fun)
print(co2)
print(type(co2)) -- 返回的 是 function 函数类型print(**********协程的运行************)
--第一种方式 对于的 是通过 create创建的协程
coroutine.resume(co)
--第二种方式
co2()print(**********协程的挂起************)
fun2 function()local i 1while true doprint(i)i i 1--协程的挂起函数coroutine.yield(i)print(coroutine.status(co3))print(coroutine.running())end
endco3 coroutine.create(fun2)
--默认第一个返回值 是 协程是否启动成功
--第二个返回值是 yield里面的返回值
isOk, tempI coroutine.resume(co3)
print(isOk, tempI)
isOk, tempI coroutine.resume(co3)
print(isOk, tempI)
isOk, tempI coroutine.resume(co3)
print(isOk, tempI)co4 coroutine.wrap(fun2)
--co4()
--co4()
--co4()
--这种方式的协程 也可以有返回值 只是没有默认第一个返回值了
print(返回值..co4())
print(返回值..co4())
print(返回值..co4())print(**********协程的状态************)
-- coroutine.status(协程对象)
-- dead 结束
-- suspended 暂停
-- running 进行中
print(coroutine.status(co3))
print(coroutine.status(co))--这个函数可以得到当前正在 运行的协程的线程号
print(coroutine.running()) 14.元表
注知识点较多要配合视频复习 print(************元表**********)
print(************元表概念**********)
--任何表变量都可以作为另一个表变量的元表
--任何表变量都可以有自己的元表父
--当我们子表中进行一些特定操作时
--会执行元表中的内容
print(************设置元表**********)
meta {}
myTable {}
--设置元表函数
--第一个参数 子表
--第二个参数 元表父
setmetatable(myTable, meta)print(************特定操作**********)
print(************特定操作-__tostring**********)
meta2 {-- 当子表要被当做字符串使用时 会默认调用这个元表中的tostring方法__tostring function(t) -- tostring 前面有两条下划线return t.nameend
}
myTable2 {name Sunset2
}
setmetatable(myTable2, meta2)
print(myTable2) --输出 Sunset2print(************特定操作-__call**********)
meta3 {-- 当子表要被当做字符串使用时 会默认调用这个元表中的tostring方法__tostring function(t) -- tostring 前面有两条下划线return t.nameend,--当子表被当做一个函数来使用时 会默认调用这个 __call中的内容--当希望传参数时 一定要记住 默认第一个参数 是调用者自己__call function(a, b)print(a)print(b)print(山有木兮)end
}
myTable3 {name Sunset2
}
setmetatable(myTable3, meta3)
--把子表当做函数使用 就会调用元表的 __call方法
myTable3(1) -- 输出 Sunset2 1 山有木兮print(************特定操作-运算符重载**********)meta4 {--相当于运算符重载 当子表使用运算符时 会调用该方法--运算符__add function(t1, t2)return t1.age t2.ageend, -- 记得打逗号 不然会报错--运算符-__sub function(t1, t2)return t1.age - t2.ageend,--运算符 *__mul function(t1, t2)return t1.age * t2.ageend,--运算符 /__div function(t1, t2)return t1.age / t2.ageend,--运算符 %__mod function(t1, t2)return t1.age % t2.ageend,--运算符 ^__pow function(t1, t2)return t1.age ^ t2.ageend,--运算符 __eq function(t1, t2)return t1.age t2.ageend,--运算符 __lt function(t1, t2)return falseend,--运算符 __le function(t1, t2)return tureend,--运算符 ..__concat function(t1, t2)return 567end,}
myTable4 {age 1}
setmetatable(myTable4, meta4)
myTable5 {age 2}
setmetatable(myTable5, meta4)print(myTable4 myTable5)
print(myTable4 - myTable5)
print(myTable4 * myTable5)
print(myTable4 / myTable5)
print(myTable4 % myTable5)
print(myTable4 ^ myTable5)--如果要用条件运算符 来比较两个对象
--这两个对象的元表一定要一致 才能准确调用方法
print(myTable4 myTable5)
print(myTable4 myTable5)
print(myTable4 myTable5)
print(myTable4 .. myTable5)print(************特定操作-__index和__newIndex**********)meta6Father {age 1
}
meta6Father.__index meta6Fathermeta6 {--age 1--__index {age 1}
}
--__index 的赋值 写在外面来初始化
meta6.__index meta6
--meta6.__index {age 1}myTable6 {}
setmetatable(meta6, meta6Father)
setmetatable(myTable6, meta6)
--得到元表的方法
print(getmetatable(myTable6))-- __index 当子表中 找不到某一个属性时
-- 会到元表中 _index指定的表去找属性
print(myTable6.age)
--rawget 当我们使用它时 会去找自己身上有没有这个变量
--myTable6.age 6
print(rawget(myTable6, age))-- __newIndex 当赋值时如果赋值一个不存在的索引
-- 那么会把这个值赋值到newindex所指的表中 不会修改自己
meta7 {}
meta7.__newindex {}
myTable7 {}
setmetatable(myTable7, meta7)
myTable7.age 7
print(myTable7.age)
print(meta7.__newindex.age)
--rawset 该方法 会忽略newindex的设置 只会改自己的变量
rawset(myTable7, age, 2)
print(myTable7.age) 15.面向对象 封装 print(**********面向对象****************)
print(**********封装****************)
--面向对象 类 其实都是基于 table来实现
--也会元表相关的知识点
Object {}
Object.id 1function Object:Test()print(self.id)
end-- 完成 new 对象的操作
-- 冒号 是会自动将调用这个函数的对象 作为第一个参数传入的写法
function Object:new()--self 代表的是 我们默认传入的第一个参数--对象就是变量 返回一个新的变量--返回出去的内容 本质就是表对象local obj {}--元表知识 __index 当找自己的变量 找不到时 就会去找元素中_index指向的内容self.__index selfsetmetatable(obj, self)return obj
endlocal myObj Object:new()
print(myObj)
print(myObj.id)
myObj:Test()
--对空表中 申明一个新的属性id不会改变元表中的
myObj.id 2
-- 总结一下找的到就用自己的找不到就用别人的谁调用用谁的self
print(Object.id) -- 还是输出 1
myObj:Test() -- 这里会输出 2print(**********继承****************)print(**********多态***************)继承 print(**********面向对象****************)
print(**********封装****************)
--面向对象 类 其实都是基于 table来实现
--也会元表相关的知识点
Object {}
Object.id 1function Object:Test()print(self.id)
end-- 完成 new 对象的操作
-- 冒号 是会自动将调用这个函数的对象 作为第一个参数传入的写法
function Object:new()--self 代表的是 我们默认传入的第一个参数--对象就是变量 返回一个新的变量--返回出去的内容 本质就是表对象local obj {}--元表知识 __index 当找自己的变量 找不到时 就会去找元素中_index指向的内容self.__index selfsetmetatable(obj, self)return obj
endlocal myObj Object:new()
print(myObj)
print(myObj.id)
myObj:Test()
--对空表中 申明一个新的属性id不会改变元表中的
myObj.id 2
-- 总结一下找的到就用自己的找不到就用别人的谁调用用谁的self
print(Object.id) -- 还是输出 1
myObj:Test() -- 这里会输出 2print(**********继承****************)
--C# class 类名 : 继承类
--写一个用于继承的方法
function Object:subClass(className)-- _G知识点 是总表 所有声明的全局标量 都以键值对的形式存在其中_G[className] {}--写相关继承的规则--要用到元表local obj _G[className]self.__index selfsetmetatable(obj, self)
endObject:subClass(Person)
--print(Person)
--print(Person.id)local p1 Person:new()
print(p1.id) -- 还是打印的 Object 的 id 1
p1.id 100
print(p1.id)
p1:Test()Object:subClass(Monster)
local m1 Monster:new()
print(m1.id)
m1.id 200
print(m1.id)
m1:Test()-- 补充 _G 的一些其他用法
--print(_G) --输出 table 加 地址 _G本质也是一张表
--_G[a] 1
--_G.b 123
--print(a) -- 1
--print(b) -- 123print(**********多态***************)多态 print(**********面向对象****************)
print(**********封装****************)
--面向对象 类 其实都是基于 table来实现
--也会元表相关的知识点
Object {}
Object.id 1function Object:Test()print(self.id)
end-- 完成 new 对象的操作
-- 冒号 是会自动将调用这个函数的对象 作为第一个参数传入的写法
function Object:new()--self 代表的是 我们默认传入的第一个参数--对象就是变量 返回一个新的变量--返回出去的内容 本质就是表对象local obj {}--元表知识 __index 当找自己的变量 找不到时 就会去找元素中_index指向的内容self.__index selfsetmetatable(obj, self)return obj
endlocal myObj Object:new()
print(myObj)
print(myObj.id)
myObj:Test()
--对空表中 申明一个新的属性id不会改变元表中的
myObj.id 2
-- 总结一下找的到就用自己的找不到就用别人的谁调用用谁的self
print(Object.id) -- 还是输出 1
myObj:Test() -- 这里会输出 2print(**********继承****************)
--C# class 类名 : 继承类
--写一个用于继承的方法
function Object:subClass(className)-- _G知识点 是总表 所有声明的全局标量 都以键值对的形式存在其中_G[className] {}--写相关继承的规则--要用到元表local obj _G[className]-- 子类 定义个base属性 base属性代表父类obj.base selfself.__index selfsetmetatable(obj, self)
endObject:subClass(Person)
--print(Person)
--print(Person.id)local p1 Person:new()
print(p1.id) -- 还是打印的 Object 的 id 1
p1.id 100
print(p1.id)
p1:Test()Object:subClass(Monster)
local m1 Monster:new()
print(m1.id)
m1.id 200
print(m1.id)
m1:Test()-- 补充 _G 的一些其他用法
--print(_G) --输出 table 加 地址 _G本质也是一张表
--_G[a] 1
--_G.b 123
--print(a) -- 1
--print(b) -- 123print(**********多态***************)
--多态相同行为 不同表现 就是多态
-- 相同方法 不同执行逻辑 就是多态
Object:subClass(GameObject)
GameObject.posX 0
GameObject.posY 0
function GameObject:Move()self.posX self.posX 1self.posY self.posY 1print(self.posX)print(self.posY)
endGameObject:subClass(Player)
-- 这样就已经实现了多态的 相同方法 不同表现 但是问题来了 我们如何保留父类的逻辑
function Player:Move()--base 指定是 GameObject 表类--这种方式调用 相当于是把基类表 作为第一个参数传入方法中--导致它们都在共用 GameObject中的Move方法数据--self.base:Move() --通过 记录的base 来保留父类的方法逻辑--我们如果要执行父类逻辑 我们不要直接使用冒号调用--要通过 . 来调用 然后自己传入第一个参数self.base.Move(self)
endlocal p1 Player:new()
p1:Move()
p1:Move()-- but 目前这种写法 有bug 不同对象使用的成员变量 是相同的成员变量
-- 并没有使用它们自己的
local p2 Player:new()
p2:Move() 总结
--面向对象实现
--万物之父 所有对象的基类 Object-- 封装
Object {}--实例化方法
function Object:new()local obj {}--给空对象设置元表 以及 __indexself.__index selfsetmetatable(obj, self)return obj
end--继承
function Object:subClass(className)--根据名字生成一张表 就是一个类_G[className] {}local obj _G[className]--设置自己的“父类”obj.base self--给子类设置元表 以及 __indexself.__index selfsetmetatable(obj, self)
end-- 多态 一般是在使用中的一种表现--测试
--申明一个新的类
Object:subClass(GameObject)
--成员变量
GameObject.posX 0
GameObject.posY 0
--成员方法
function GameObject:Move()self.posX self.posX 1self.posY self.posY 1
end--实例化对象使用
local obj GameObject:new()
print(obj.posX)
obj:Move()
print(obj.posX)local obj2 GameObject:new()
print(obj2.posX)
obj2:Move()
print(obj2.posX)--申明一个新的类 Player 继承 GameObject
GameObject:subClass(Player)
--多态 重写 GameObject的Move方法
function Player:Move()--base调用父类方法 用 . 自己传第一个参数self.base.Move(self)
endprint(*******)
--声明实例化 Player对象
local p1 Player:new()
print(p1.posX)
p1:Move()
print(p1.posX)local p2 Player:new()
print(p2.posX)
p2:Move()
print(p2.posX) 16.自带库 print(************自带库*********)
--string
--table
print(************数字运算*********)
--系统时间
print(os.time())
--自己传入参数 得到时间
print(os.time({year 2014, month 8, day 14}))-- os.date(*t)
local nowTime os.date(*t)
for k,v in pairs(nowTime) doprint(k,v)
end
print(nowTime.day)
print(nowTime.hour)print(************数学运算*********)
--math
--绝对值
print(math.abs(-11))
--弧度转角度
print(math.deg(math.pi))
--三角函数 传的是弧度
print(math.cos(math.pi)) --其它的sin...都是这样--向下向上取整
print(math.floor(2.6))
print(math.ceil(5.1))--最大最小值
print(math.max(1,2))
print(math.min(4,5))--小数分离 分成整数部分和小数部分
print(math.modf(1.2)) -- 1 0.2-- 幂运算 还有^ 也是
print(math.pow(2, 5))--随机数
--先设置随机数种子
math.randomseed(os.time())
print(math.random(100))
print(math.random(100))--开方 就是开根号
print(math.sqrt(9))print(************路径*********)
--lua脚本加载路径
print(package.path)
package.path package.path .. ;C:\\
print(package.path)17.Lua垃圾回收