Lua语法

第一个语法

打印

print("你好")

注释

--单行注释
--lua可以省略分号
--[[
多行注释
]]

--[[
第二种多行注释
]]--

--[[
第三种多行注释
--]]

变量

简单变量

print("**********变量**********")
-- 简单变量
-- nil number string boolean
--不用申明变量类型 会自己判断
--类似C#中的var
--lua中的变量可以 随便赋值 ——自动识别类型

--通过type函数可以得到变量类型
--type返回string类型

--lua中没定义的变量
--默认为nil,不会报错
print(b)

-- nil 类似 C#中的null
a = nil
print(a)
print(type(a))
--number 所有数值都是number

a=1
print(a)
print(type(a))
a = 1.2
print(a)
print(type(a))

--string 字符串申明 用单/双引号
--lua 中没有char
a = "12345"
print(a)
print(type(a))
a = '123'
print(a)
print(type(a))

--boolean
a = true
print(a)
print(type(a))
a = false
print(a)
print(type(a))

--type返回string
print(type(type(a)))

Lua总共有8种变量类型

简单变量

number, string, boolean, nil

复杂变量

function 函数        table 表        userdata 数据结构        thread 协同程序

字符串操作

print("*****字符串*****")
str = "双引号字符串"
str2 = '单引号字符串'

--获取字符串的长度
print("***字符串长度***")
s = "1234567字符串"
--一个汉字占3个长度
--英文字符 1个
print(#s)

print("***多行打印***")
--lua也支持转义字符
print("123\n123")

s = [[我是
阿喆
不想学习
]]
print(s)

print("***字符串拼接***")
--字符串拼接 通过..
print("123".."456")
s1 = 111
s2 =  111
--number 拼接后也是 string
print(s1 .. s2)
print(type(s1 .. s2))

print(string.format("我是阿喆不想学习,我今年%d岁了",18))
--%d : 与数字拼接
--%a : 与任何字符拼接 format中用不了,
--%s : 与字符配对
--........

print("***别的类型转字符串***")
a = true
print(tostring(a))

print("***字符串提供的公共方法***")
str = "abCdeFg"
--小写转大写
print(string.upper(str))
print(str) --本体不变
--大写转小写
print(string.lower(str))
--翻转字符串
print(string.reverse(str))
--字符串索引查找 返回开始和结束位置 从1开始
print(string.find(str,"Cde"))
--截取字符串
print(string.sub(str,3)) --截取第3个及之后所有字符
print(string.sub(str,3,4)) --截取第3到第4个字符
--字符串重复
print(string.rep(str,2)) --连续拼接2次
--字符串修改
--返回修改后的,并显示改了几次,若有2个Cd,则会返回2
print(string.gsub(str,"Cd","**")) 
print(string.gsub("abcde123","%a","4")) --44444123 5
print(string.gsub("abcde123","a","4")) --4bcde123 1
print(string.gsub("abcde123","%A","4")) --abcde444 3


--字符转 ASCII码
a = string.byte("Lua",1)
--把第一个字符转成了ASCII码
print(a)
--ASCII码 转字符
print(string.char(a))

返回值

print("***运算符***")
print("***算数运算符***")
-- + - * / % ^
-- 没有自增自减 ++ --
-- 没有复合运算符 += -= /= *= %=
--字符串 可以进行 算数运算符操作 会自动转成number
print("加法运算 1 + 2")
--print("加法运算" .. 1 + 2) 会输出"加法运算3"
a = 1
b = 2
print(a + b)
print("123.4" + 1) -- 124.4
--其它运算符一样
--注意除法不会向下取整
print("123.4" / 2) -- 61.7
print("123.4" % 2) -- 1.4

-- lua 中 ^ 为幂运算
print("幂运算" .. 2 ^ 5)
print("123.4" ^ 2) -- 15227.56

print("***条件运算符***")
-- > < >= <= == ~=
--不等于不一样

print("***逻辑运算符***")
-- && || ! 
-- and or not  Lua用这个
-- lua满足“短路” 比如and第一个已经是假 则后面不会执行
print( true and false)

print("***位运算符***")
-- & | 不支持位运算 需要自己实现

print("***三目运算符***")
-- ? :   lua中不支持

条件分支语句

print("***条件分支语句***")
a = 9
-- if 条件 then ... end
if a > 5 then
	print("123")
end

if a < 5 then
	print("123")
else
	print("321")
end

--多分支 elseif 连着写
if a < 5 then
	print("123")
elseif a == 9 then
	print("6")
else
	print("321")
end

if a >= 3 and a <= 9 then
	print("9")
end

--lua中无 switch语法

循环语句

print("***循环***")

print("***while***")
num = 0
--while 条件 do ... end
while num < 5 do
	print(num)
	num = num + 1
end

print("***do while***")
num = 0
--repeat ... until 结束条件
repeat
	print(num)
	num = num + 1
until num > 5 --满足条件跳出

print("***for***")
-- i 从 1 到 5
for i = 1, 5 do --默认递增 i会默认加一
	print(i)
end

for i = 1, 5, 2 do --自定义增量 直接逗号后面写
	print(i)
end

for i = 5, 1, -1 do --自定义增量 直接逗号后面写
	print(i)
end

函数

print("***函数***")
--function 函数名()
--end

--a = function()
--end

print("***无参无返回值***")
-- 要先声明才能调用
function  F1()
	print("F1函数")
end
F1()

--有点类似C#中的委托和事件
F2 = function()
	print("F2函数")
end
F2()

print("***有参数***")
--参数类型不指定,可以任意传参(只要函数体支持该操作)
function F3(a)
	print(a)
end
F3(1)

--如果传入参数和函数参数个数不匹配
--不会报错 只会不空nil 或丢弃
F3()
F3(1,2,3)

print("***有返回值***")
function F4(a)
	return a
end
temp = F4("123")
print(temp)

function F5(a)
	return a,"123",true
end
 -- 用对应数量的变量来赋值
 -- 变量不够 会丢弃后面两个返回值
 -- 变量多了 赋nil
temp = F4("1")
temp1,temp2,temp3 = F5("1")
print(temp1)
print(temp2)
print(temp3)

print("***函数的类型***")
--函数类型就是function
F6 = function()
	print("123")
end
print(type(F6))

print("***函数的重载***")
--函数名相同 参数类型不同 或者参数个数不同
--但lua中参数类型没要求
--所以不支持重载
--只会调用最后申明的同名函数

print("***变长参数***")
--变长参数使用 用一个表存起来 再用
function F7( ... )
	arg = {...}
	for i = 1, #arg do
		print(arg[i])
	end
end
F7(1,"123",true,4,5,6)

print("***函数嵌套***")

function F8()
	return function()
		print(123)
	end
end

f9 = F8()
f9()

--闭包
function F9(x)
	--改变了传入参数的生命周期
	--外部的x被传入了内部的函数
	return function(y)
		return x - y
	end
end

f10 = F9(10)
--x被存进去了
print(f10(5)) --5

在lua中闭包的体现在哪里

是函数中返回一个函数,改变函数中变量的生命周期

table

table实现数组

print('***复杂数据类型 table***')
--所有的复杂类型 都是table

print('***数组***')
a = {1,2,nil,3,4,"12345",6,true,nil,7}
--lua中索引从1开始 a[0]是nil
print(a[5])

-- #是通用的获取长度的关键字
--在打印长度的时候 nil会被忽略
--遍历时 碰到 nil 就会断,则返回长度可能不对
print(#a)

print('***数组的遍历***')
for i = 1, #a do
	print(a[i])
end

print("***二维数组***")
a = {{1,2,3},
	 {4,5,6}}
print(a[1][2])


print("***二维数组遍历***")
for i = 1, #a do
	b = a[i]
	for j = 1, #b do
		print(b[j])
	end
end

print("***自定义索引***")

aa = {[0] = 1, 2,3, [-1] = 4, 5}
print(aa[0]) -- 1
print(aa[1]) -- 2
print(aa[-1]) -- 4
--不认识[0], [-1]
print(#aa) -- 3

--中间断一个 输出最大
aa = {[1] = 1,[2] = 2,[4] = 3, [5] = 4}
print(#aa) -- 5

--断的多余1个
aa = {[1] = 1,[2] = 2,[5] = 3, [-1] = 4, 5}
print(#aa) -- 2

注意: #a 碰到nil 会不会停要看lua版本,我的lua为5.1.4,碰到nil不停,

迭代器遍历

print("***迭代器遍历***")
--迭代器遍历 主要用来遍历表
--#得到长度 并不准确 一般不用#来遍历表

a = {[0] = 1, 2, [-1] = 3, 4, 5}
print("***ipairs迭代器遍历***")
--ipairs
--ipairs遍历 还是从1开始遍历,小于等于0的值得不到
--只能找连续索引的 键 如果中间断序了 也无法遍历出后面的内容
for i,k in ipairs(a) do
	print("ipairs遍历键值"..i.."_"..k)
end

print("***pairs迭代器遍历***")
--能把所有的键都找到
for i,v in pairs(a) do
	print("pairs遍历键值"..i.."_"..v)
end

print("***pairs迭代器遍历键***")
--能把所有的键都找到
for i in pairs(a) do
	print("pairs遍历键"..i)
end

table实现字典

print('***复杂数据类型 table2***')
print('***字典***')
print('***字典的申明***')
--字典由键值对构成
a = {["name"] = "阿喆", ["age"] = 20, ["1"] = 5}
--访问单个变量 中括号中填键
print(a["name"])
--还可以类似.成员变量的形式得到值,但不能是数字
print(a.name)
--  print(a.1) 会报错
print(a["1"])

--修改
a["name"] = "azhe"
print(a.name)

--新增
a["sex"] = false
print(a.sex)

--删除
a["sex"] = nil
print(a.sex)
--其实没有也会打印出空

print('***字典的遍历***')
--模拟字典 只能用pairs
for k,v in pairs(a) do
	--可以传多个参数 一样可以打印
	print(k,v)
end

for k in pairs(a) do
	print(k)
	print(a[k])
end

table实现类

print('***类和结构体***')

--lua中默认没有面向对象的 要我们自己来实现
--成员变量 成员函数
Student = {
	age = 1,
	sex = true,

	Up = function()
		--这样写 这个age是全局变量,和表中的age没有任何关系
		--print(age)
		--要表明是谁的 才能调用表本身的属性或方法
		print(Student.age)
		print("我成长了")
	end,

	Learn = function(t)
		--第二种 在函数内部调用自己属性或者方法的方法
		--把自己作为一个参数传进来 在内部访问
		print(t.sex)
		print("好好学习")
	end
}
--C#要使用类 实例化对象new 静态
--lua中类的表现 更像是一个类中有很多 静态变量和函数
print(Student.age)
Student.Up()

--申明表过后,在表外去申明表的变量和方法
Student.name = "阿喆"
Student.speak = function ()
	print("说话")
end
--函数的第三种申明方式
function Student.speak2()
	print("说话2")
end

function Student:speak3()
	--lua中 有一个关键字self (不是this) 表示 默认传入的第一个参数
	print(self.name.."说话3")
end

Student.Learn(Student)
--lua中 . 和 冒号的区别
--冒号调用方法 会默认把调用者 作为第一个参数传入方法中
Student:Learn()

Student:speak3()
Student.speak3(Student)

注意:

当定义冒号调用方法时,如例子Student:Learn(),当定义该方法后,Student表里就会存放该Learn方法。 在后续实现面向对象的过程中,多态就靠这个实现。

表的公共操作

print('***表的公共操作***')
--表中 table提供的一些公共方法的讲解

t1 = {{age = 1, name = "123"}, { age = 2, name = "345"}}

t2 = {name = "唐老狮", sex = true}

--插入
print(#t1)
--插到t1后面
table.insert(t1,t2)
print(#t1)
print(t1[1])
print(t1[2])
print(t1[3])
print(t1[3].sex)

--删除指定元素
-- remove 方法 传1个参数进去 会移除最后一个索引的内容
table.remove(t1)
print(#t1)
print(t1[1].name)

--remove 方法 传2个参数进
--参数2 要移除内容的索引
table.remove(t1,1)
print(t1[1].name)
print(#t1)

print('***排序***')
t2 = {5,2,3,7,1}
table.sort(t2) --从小到大
for _,v in pairs(t2) do
	print(v)
end

print('***降序***')
--参数二 排序规则函数
table.sort(t2, function(a,b) 
	if a > b then
		return true
	end
end
)
for _,v in pairs(t2) do
	print(v)
end


print("***拼接***")
tb = {1,"123", "456","789"}
--数字和字符串可以拼,其它报错 (nil放最后不报错)
--连接函数 用于拼接表中元素 返回值 是一个字符串
str = table.concat(tb,",")
print(str)

多lua脚本执行

全局变量和本地变量

print('***全局变量和本地变量***')
--全局变量
a = 1
b = "123"

for i = 1,2 do 
	c = "azhe"
end

print(c) -- azhe

--本地(局部) 变量的关键字 local
for i = 1,2 do 
	local d = "azhe"
	print("循环中的d",d)
end

print(d) -- nil

fun = function()
	tt = "123123"
end

print(tt) -- nil

fun() --执行后tt赋值了
print(tt) -- 123123

local tt2 = "555"
print(tt2)

多脚本执行

print('***多脚本执行***')
--关键字 require("脚本名") require('脚本名')
require("Test")
print(testA) --123
print(testLocalA) --nil

local testLA = require("Test")
print(testLA) -- 456

Test脚本

print("Test测试")
testA = "123"
local testLocalA = "456"
--其它脚本require的时候会正常输出
print(testLocalA) -- 456
--可以return出去
return testLocalA

脚本卸载

print('***脚本卸载***')
--如果是require加载执行的脚本 加载一次后不会再被执行
require("Test") --没输出Test测试
--package.loaded["脚本名"]
--返回值是boolean 意思是 脚本是否被执行
print(package.loaded["Test"]) -- true
--卸载已经执行过的脚本
package.loaded["Test"] = nil
print(package.loaded["Test"]) --nil

_G表

print('***大G表***')
-- _G表是一个总表(table) 他将我们申明的所有全局的变量都存储在其中
for k,v in pairs(_G) do
	print(k,v)
end
--本地变量 加了local的变量不会存到_G表中

特殊用法

print("***特殊用法***")
print("***多变量赋值***")
a,b,c = 1,2,"123"
print(a,b,c) -- 1  2  123
--多变量赋值 如果后面的值不够会补空
a,b,c = 1,2
print(a,b,c) -- 1  2  nil
--后面值多了会省略
a,b,c = 1,2,"123",12
print(a,b,c) -- 1  2  123

print("***多返回值***")
function Test()
	return 10,20,30,40
end
--多返回值 你用几个变量接,就有几个值
--少了就少接,多了就补空
a,b,c = Test()
print(a,b,c)


print("***and or***")
--逻辑与 逻辑或
--and or 不仅可以连接 boolean 任何东西都可以用来连接
--在lua中 只有nil 和false 才认为是假
-- "短路" 对于and来说 有假则假 对于or来说 有真则真
--所以第一个满足条件了 就停止计算
print(1 and 2) --2
print(0 and 2) --0
print(nil and 1) --nil
print(false and 2) -- false
print(true and 3) --3

print(true or 1) --true
print(false or 1) -- 1
print(nil or 2) --2

--lua不支持三目运算符
x = 1
y = 2
-- ? :
--但可以通过"短路"特性来模拟
local res = (x > y) and x or y
print(res) -- 2
-- (x > y) and x -> x
-- x or y -> y

x = 2
y = 3
local res = (x > y) and x or y
print(res) -- 3
-- (x > y) and x -> (x>y)
-- (x>y) or y -> y  -> y

协同程序

print("***协同程序***")

print("***协程的创建***")
--coroutine.creata()
fun = function()
	print(123)
end

co = coroutine.create(fun)
--协程的本质是一个线程对象
print(co) -- thread: 00C9DA48
print(type(co)) -- thread

--coroutine.wrap() 第二种方式
co2 = coroutine.wrap(fun)
print(co2) --function: 00CAE428
print(type(co2)) --function

print("***协程的运行***")
--第一种方式 对应的是 create创建的
coroutine.resume(co)

--第二种方式 调用函数 co2
co2()

print("***协程的挂起***")
fun2 = function()
	local i = 1
	while true do
		print(i)
		i = i + 1
		--协程的挂起函数
		--可以带返回值
		--默认第一个是协程是否启动成功
		--第二个是yield中的返回值
		coroutine.yield(i)
	end
end

co3 = coroutine.create(fun2)
--重启协程的函数
isOk,tempI = coroutine.resume(co3)  --1
print(isOk,tempI)
--只打印一次
--因为lua中从上到下只执行一次
coroutine.resume(co3)  --2

co4 = coroutine.wrap(fun2)
--会先输出co4()中的print(i),然后直接返回返回值,没有默认第一个返回值
print("返回值",co4())
co4() --2

print("***协程的状态***")
--coroutine.status(协程对象)
--dead 结束
--suspended 暂停
--running 进行中
print(coroutine.status(co)) --dead
print(coroutine.status(co3)) --suspend
--在内部运行 得到running

--这个函数可以得到当前 正在运行的协程的线程号
print(coroutine.running())

元表

print("***元表***")
print("***元表概念***")
--任何表变量都可以作为另一个表变量的元表
--任何表变量都可以有自己的元表(爸爸)
--当我们子表中进行一些特定操作时
--会执行元表中的内容
print("***设置元表***")
meta = {}
myTable = {}
--设置元表函数
--参数一 子表
--参数二 元表(爸爸)
setmetatable(myTable,meta)


print("***特定操作***")
print("***特定操作-__tostring***")
meta2 = {
	--当子表要被当做字符串使用时,会默认调用这个元表中的tostring方法
	__tostring = function()
		return "阿喆"
	end
}
myTable2 = {name = "阿喆2"}
--设置元表函数
--参数一 子表
--参数二 元表(爸爸)
setmetatable(myTable2,meta2)
print(myTable2)

meta2 = {
	--当子表要被当做字符串使用时,会默认调用这个元表中的tostring方法
	--会默认传入自己 myTable2
	__tostring = function(t)
		return t.name
	end
}
myTable2 = {name = "阿喆2"}
--设置元表函数
--参数一 子表
--参数二 元表(爸爸)
setmetatable(myTable2,meta2)
print(myTable2)

print("***特定操作-__call***")
meta3 = {
	--当子表要被当做字符串使用时,会默认调用这个元表中的tostring方法
	--会默认传入自己 myTable2
	__tostring = function(t)
		return t.name
	end,
	--当子表被当作一个函数来使用时,会默认调用这个__call的内容
	__call = function(a,b)
		--a是自己,第一个参数默认是自己
		--当需要传参数时,记住默认第一个参数是自己
		print(a) -- 阿喆3
		print(b) -- 1
		print("阿喆好努力")
	end
}
myTable3 = {name = "阿喆3"}
setmetatable(myTable3,meta3)
--把子表当函数使用 会调用元表的__call方法
myTable3(1) 

print("***特定操作-运算符重载***")
meta4 = {
	--运算符+
	__add = function(t1,t2)
		return t1.age + t2.age
	end,
	--运算符-
	__sub = function(t1,t2)
		return t1.age - t2.age
	end,
	--运算符*
	__mul = function(t1,t2)
		return t1.age * t2.age
	end,
	--运算符/
	__div = function(t1,t2)
		return t1.age / t2.age
	end,
	--运算符%
	__mod = function(t1,t2)
		return t1.age % t2.age
	end,
	--运算符^
	__pow = function(t1,t2)
		return t1.age ^ t2.age
	end,
	--运算符==
	__eq = function(t1,t2)
		return t1.age == t2.age
	end,
	--运算符<   没有 > >=
	__lt = function(t1,t2)
		return t1.age < t2.age
	end,
	--运算符<=
	__le = function(t1,t2)
		return t1.age <= t2.age
	end,
	--运算符..
	__concat = function(t1,t2)
		return t1.age..t2.age
	end
}
myTable4 = {age = 2}
setmetatable(myTable4,meta4)
myTable5 = {age = 2}
print(myTable4 + myTable5)

--如果要用条件运算符 来比较两个对象
--这两个对象的元素一定要一致 才能准确调用方法
print(myTable4 == myTable5) -- false
setmetatable(myTable5,meta4)
print(myTable4 == myTable5) -- true

print("***特定操作-__index和__newindex***")
meta6 = {
	age = 1
}

myTable6 = {}
setmetatable(myTable6,meta6)

--__index 当子表中 找不到某一个属性时
--会到元表中 __index指定的表去找索引
print(myTable6.age) -- nil
meta6.__index = meta6
print(myTable6.age) -- 1

--或者mata6中没有age,但index指向一个新的表
meta6.__index = {age = 2}
print(myTable6.age) -- 2

--建议__index的赋值 写在表外面来初始化
--__index没有赋值的话是找不到的



--__newindex 当赋值时,如果赋值一个不存在的索引
--那么会把这个值赋到newindex所指的表中 不会修改自己
meta7 ={}
myTable7 = {}
setmetatable(myTable7,meta7)
meta7.__newindex = {}
myTable7.age = 1
--在myTable7中找不到,newindex设置了,则会加到__newindex中
print(myTable7.age) -- nil
print(meta7.__newindex.age) -- 1


--获取元表
--得到元表
print(getmetatable(myTable6)) --table: 00C31290
--rawget 当我们使用他时,会去找自己身上有没有这个变量,不看元表的index了
print(rawget(myTable6,"age")) -- nil

--即使有__newindex,也会忽略,只改自己的变量
rawset(myTable7,"age",2)
print(myTable7.age) -- 2

疑惑与解决

在后续实现面向对象的过程中,p1调用父类的move方法后,发现p1表中也有了posX和posY,且父类GameObject的PosX和posY没有变,而p1的pos值变了,因此有了疑惑做了以下试验

s = {}
function s:fun()
	self.A = 10
end

s:fun()

以上操作s中会创建A元素等于10。

s = {}
function s:fun()
	self.A = self.A+10
end

s:fun()

这样就会出错,因为s中没有A

因此可以这样写

father = {}
father.__index = father
s = {}
setmetatable(s,father)
father.A = 10

function s:fun()
	self.A = self.A+10
end

s:fun()

这样子就可以执行,因为设置元表,找到了father的index中的A,那么输出就会发现,s中有A为20,father中的A仍为10

因此我推测index中的值只是供s参考,因此等号右边的self.A会找到father的index中的值,等号左边的self.A则会在s中创建A。

面向对象

封装

print("***面向对象***")
print("***封装***")
--面向对象 类 其实都是基于表 table 来实现
--元表相关知识点
Object = {}
Object.id = 1

function Object:Test()
	print(self.id)
end

--冒号 自动将调用这个函数的对象 作为第一个参数传入的写法
function Object:new()
	--self 代表的是我们默认传入的 第一个参数
	--对象就是变量 返回一个新的变量
	--返回出去的内容 本质上就是表对象
	local obj = {}
	--元表知识 __index 当找自己的变量 找不到时,会找元表中__index中的内容
	self.__index = self
	setmetatable(obj,self)
	return obj
end

local myObj = Object:new()
print(myObj) --table: 00CB96D0
-- nil 没设置元表以及元表的index时
-- 1 设置元表及其__index后
print(myObj.id) 
Object:Test() -- 1

--在空表中 申明一个新的属性 
myObj.id = 2
print(Object.id) -- 1 
myObj:Test() -- 2

继承

print("***继承***")
--C# class 类名 : 继承类
--写一个用于继承的方法
function Object:subClass(className)
	-- _G知识点 总表, 所有声明的全局变量,都以键值对的形式存在其中
	_G[className] = {}
	--写继承规则
	--用到元表
	local obj = _G[className]
	self.__index = self
	setmetatable(obj,self)
end

Object:subClass("Person")
print(Person) --table: 00EA9AE0
print(Person.id) -- 1

local p1 = Person:new()
print(p1.id) -- 1
--p1无id,找person,person的__index也无
--再往上找Object的__index

多态

...
function Object:subClass(className)
	-- _G知识点 总表, 所有声明的全局变量,都以键值对的形式存在其中
	_G[className] = {}
	--写继承规则
	--用到元表
	local obj = _G[className]
	self.__index = self
	--子类 定义个base属性 base表示父类
	obj.base = self
	setmetatable(obj,self)
end
...

print("***多态***")
--相同行为 不同表现 就是多态
--相同方法 不同执行逻辑 就是多态
Object:subClass("GameObject")
GameObject.posX = 0
GameObject.posY = 0
function GameObject:Move()
	self.posX = self.posX + 1
	self.posY = self.posY + 1
	print(self.posX)
	print(self.posY)
end

GameObject:subClass("Player")

local p1 = Player:new()
p1:Move() -- 1 \n 1

--重写
function Player:Move()
	--c#中保留父类方法 base.Move()
	--为了实现,要去继承那里定义base属性
	--self.base:Move()
	--重点
	--base指的是 GameObject 表(类)
	--这种方式调用 相当于是把基类表 作为第一个参数传入了方法中
	--避免把基类表 传入到方法中 这样相当于公用一张表的属性了
	--如果要执行父类逻辑 不要直接使用冒号调用
	--要通过.调用,然后自己传入第一个参数
	self.base.Move(self)

	
end
p1:Move() -- 2 \n 2

local p2 = Player:new()
p2:Move() -- 改前 2 \n 2
			--改后 1 \n 1
--p1 和 p2 共用

--(没有改成重点之后的内容前)以上写法有坑 不同对象使用的成员变量 居然是相同的成员变量

汇总

--面向对象实现
--万物之父 所有对象的基类 Object
--封装
Object = {}
--实例化方法
function Object:new()
	local obj = {}
	--给空对象设置元表 以及__index
	self.__index = self
	setmetatable(obj,self)
	return obj
end

--继承
function Object:subClass(className)
	--根据名字生成一张表 就是一个类
	_G[className] = {}
	local obj = _G[className]
	--设置自己的父类
	obj.base = self
	--给子类设置元表 以及__index
	self.__index = self
	setmetatable(obj,self)
end

--申明一个新的类
Object:subClass("GameObject")
--成员变量
GameObject.posX = 0
GameObject.posY = 0
--成员方法
function GameObject:Move()
	self.posX = self.posX + 1
	self.posY = self.posY + 1
end

--实例化对象使用
local obj = GameObject:new()
print(obj.posX) --0
obj:Move()
print(obj.posX) --1

local obj2 = GameObject:new()
print(obj2.posX) --0
obj2:Move()
print(obj2.posX) --1

--声明一个新的类 Player 继承 GameObject
GameObject:subClass("Player")
--多态 重写了 GameObject中的Move方法
function Player:Move()
	--base调用父类方法 用.自己传第一个参数
	self.base.Move(self)
end

--实例化Player对象
local p1 = Player:new()
print(p1.posX) --0
p1:Move()
print(p1.posX) -- 1

local p2 = Player:new()
print(p2.posX) -- 0
p2:Move()
print(p2.posX) -- 1

自带库

print("***自带库***")
--string
--table
print("***时间***")
--系统时间
print(os.time()) --1709371947
--自己传入参数 得到事件
print(os.time({year = 2014, month = 8, day = 14})) --1407988800

--os.date("*t")
local nowTime = os.date("*t")
print(nowTime)
for k,v in pairs(nowTime) do
	print(k,v)
end
--[[
hour	17
min	35
wday	7
day	2
month	3
year	2024
sec	23
yday	62
isdst	false
]]
print(nowTime.hour) --17


print("***数学运算***")
--math
--绝对值
print(math.abs(-11)) --11
--弧度转角度
print(math.deg(math.pi)) --180
--三角函数 传弧度
print(math.cos(math.pi)) -- -1

--向下向上取整
print(math.floor(2.6)) -- 2
print(math.ceil(5.2)) -- 6

--最大最小值
print(math.max(2,6)) -- 6
print(math.min(5,2)) -- 2
 
--小数分离 分成整数部分和小数
print(math.modf(1.2)) -- 1  0.2

--幂运算
print(math.pow(2,5)) --32

--随机数
--先设置随机数种子
math.randomseed(os.time())
print(math.random(100))
print(math.random(100))
--开方
print(math.sqrt(4)) --2

print("***路径***")
--lua脚本加载路径
print(package.path)
package.path = package.path .. ";C:\\"
print(package.path)

Lua垃圾回收

print("***垃圾回收***")

test = {id = 1, name = "123456"}
--垃圾回收关键字
--collectgarbage
--获取当前lua占用内存值 K字节 用返回值*1024 就可以得到具体的内存占用字节数
print(collectgarbage("count"))
--lua中的机制 和C#中垃圾回收机制很类似 解除羁绊 就是变垃圾
test = nil
--进行垃圾回收 有点像C#的 GC
collectgarbage("collect")
print(collectgarbage("count"))

--lua中 有自动定时进行GC的方法
--Unity中热更新开发 尽量不要去用自动垃圾回收

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值