Lua学习笔记3

Lua学习笔记3

IO读写

Lua中读写使用自带的I/O库处理文件。

分为简单模式和完全模式。

  • 简单模式(simple model)拥有一个当前输入文件和一个当前输出文件,并且提供针对这些文件相关的操作。

  • 完全模式(complete model) 使用外部的文件句柄来实现。它以一种面对对象的形式,将所有的文件操作定义为文件句柄的方法

    注意:要打开的文件地址。

    打开文件的操作语句:

    file=io.open(filename[,mode])
    

    其中mode所有的值为:

    模式 描述
    “r” 以只读的方式打开文件,打开的文件要必须存在
    “w” 只写的权限打开文件,若文件存在则文件长度清为0,文件内容会消失。若文件不存在则建立该文件
    “a” 以附加的方式打开只写文件。若文件不存在,则会建立该文件,若文件内容不为空,则写入的数据会加在文件末尾,原文内容会得到保留。
    “r+” 以可读的方式打开文件,该文件必须存在
    “w+” 打开可读写文件,若文件存在则文件长度清零,若文件不存在则建立文件
    “a+” 与a类似,但是文件可读可写
    “b” 二进制模式,如果文件是二进制文件,可以加上b使用
    “+” 加号表示对文件即可读又可写
function IOText()
    filename="D:\\UnityProject\\Assets\\Scripts_lua\\Game\\Test\\IO.txt"
    --part1 简单模式打开文件练习
    --只读方式打开
    file = io.open(filename,"r")
    io.input(file)
    --输出文件的第一行
    log(io.read())
    --关闭打开的文件    
    io.close(file)

    ------------------------------
    --以附加的形式打开
    file=io.open(filename,"a")
    --设置输出的文件
    io.output(file)
    io.write("----新添加的文字")
    io.close(file)
end


function IOText1()
    filename="D:\\UnityProject\\Assets\\Scripts_lua\\Game\\Test\\IO.txt"
    --------------------part2
    --完全模式 该模式下可以在同一时间处理多个文件
    file=io.open(filename,"r")
    log(file:read())
    file:close()
    
    --以附加的形式打开
    file=io.open(filename,"a")
    file:write("----第三行新加的文字")
    file:close()
end

image-20240226114314735

function IOText2() 
    --另外可以指定文件内容位置进行读取
    filename="D:\\UnityProject\\Assets\\Scripts_lua\\Game\\Test\\IO.txt"
    file=io.open(filename,"r")
    --定位到倒数18个字符位置
    file:seek("end",-18)
    log(file:read("*a"))--从当前位置读取到结尾的内容
    file:close()
end

image-20240226115340363

错误处理

调试

垃圾回收

Lua语言采取自动内存管理。

这意味着你不用操心新创建的对象需要的内存如何分配出来, 也不用考虑在对象不再被使用后怎样释放它们所占用的内存。

Lua语言中运行着一个垃圾收集器,用来收集所有的死对象(无法访问的内存空间),来完成内存回收管理的工作。Lua中所有用到到内存的结构如字符串、表、协程、函数、内部结构等都会服从自动管理。

Lua实现一个增量标记-扫描收集器。它有两个重要的参数来控制–垃圾收集器间歇率垃圾收集器步进率,使用百分数作为单位!

垃圾收集间歇率:控制垃圾收集器需要在开启新的循环前的等待时间,值越高,开启下一轮的垃圾回收循环需要等待的时间越长,减少垃圾收集器的积极性。此值<100,则直接开启下一轮垃圾回收,无需等待;设置当前值为200时,表示当内存总使用量是之前使用量的2倍时才开启新的循环。

垃圾收集器步进率:收集器的运作速度/内存的分配速度。值越大,表示垃圾收集机制越积极。默认值是200;垃圾回收运作速度是内存分配速度的二倍。(要保证垃圾回收运作速度快于内存分配速度,只有如此内存才能尽可能的被及时补充。)

table2={"apple","pear","orange"}
print("---------------------------------")
print(collectgarbage("count"))
table2=nil
print(collectgarbage("count"))--使用的总内存数
print(collectgarbage("collect"))--进行垃圾回收
print(collectgarbage("count"))

image-20240226153735954

面向对象OOP

Shape={area=0}
--构造函数
function Shape:new (o,side)
    o=o or {}  --?
    setmetatable(o,self)
    self.__index=self --?
    side=side or 0
    self.area=side*side
    return o 
end
--基础类方法 打印出语句
--使用:表示属于Shape的类中
function Shape:printArea()
    print(self.area)
end

--新建形状对象
shape1=Shape:new(nil,10)
shape1:printArea()--打印出面积是100

image-20240226175048950

学有疑问:在Lua中‘:’,‘ .’和‘self’的区别用法?

答:https://www.cnblogs.com/suoluo/p/7368276.html

self的不同:https://xushuwei202.github.io/blog/2014/04/12/lua-self/

--面向对象
Account={balance=500}
function Account.withdraw(v)
    Account.balance=Account.balance-v
end
--进行设置

---------------------------------------------------------------
Shape={area=0}
--构造函数
function Shape:new (o,side)
    o=o or {}  --?
    setmetatable(o,self)
    self.__index=self --?
    side=side or 0
    self.area=side*side
    return o 
end
--基础类方法 打印出语句
--使用:表示属于Shape的类中
function Shape:printArea()
    print(self.area)
end

--继承
--正方形派生类
Square = Shape:new() --类中的属性
function Square:new (o,side)
    o=o or Shape:new(o,side)--父构造器
    setmetatable(o,self)
    self.__index=self
    return o
end
--正方向派生类方法 
function Square:printArea()
    print("正方形面积为",self.area)
end

--矩形派生类
Rectangle = Shape:new()
function Rectangle:new (o,length,breadth)
    o=o or Shape:new (o)
    setmetatable(o,self)
    self.__index=self
    self.area=length*breadth
    return o
end 

function Rectangle:printArea()
    print("矩形面积:",self.area)
end 

--新建对象
--新建形状对象
shape1=Shape:new(nil,10)
shape1:printArea()

--创建派生类对象--正方形
square1=Square:new(nil,10)
square1:printArea()

--创建派生类对象--矩形派生类
rectangle1=Rectangle:new(nil,5,6)
rectangle1:printArea()

image-20240226182706400

简单继承练习2

--简单继承
 function CreateRobot(name,id)
    local obj={name=name,id=id}
    --成员函数
    function obj:SetName(name)
        self.name=name
    end
    function obj:GetName()
        return self.name
    end
    function obj:SetId(id)
        self.id=id
    end
    function obj:GetId()
        return self.id
    end
    return obj
end
--派生类继承Robot类
 function createFootballRobot(name,id,position)
    log("123")
    local obj=CreateRobot(name,id)
    obj.position="right back"
    function obj:SetPosition(p)
        self.position=p
    end
    function obj:GetPosition()
        return self.position
    end
    return obj
end

函数调用:

footballRobot=createFootballRobot("TonyChang",6006,"广州")
print("footballRobot_name:",footballRobot:GetName(),"footballRobot_id",footballRobot:GetId())
print("footballRobot_position",footballRobot:GetPosition())
--更改对象内容
footballRobot:SetId(9009)
footballRobot:SetName("UrusWong")
footballRobot:SetPosition("Beijing")
print("--------------------更改之后----------------------")
print("footballRobot_name:",footballRobot:GetName(),"footballRobot_id",footballRobot:GetId())
print("footballRobot_poisition",footballRobot:GetPosition())   

image-20240227103520350

高级语言知识—

函数闭包:

函数闭包是由一个函数和它本身所有的upvalue构成的。

upvalue是指函数中使用的但定义在函数外部的局部变量。

--闭包
--作为结果将倒计时函数返回
function createCountdownTimer(second)
      local ms=second*1000 --ms为countDown函数之外的局部变量称之为upvalue 变量的定义初始化在函数外部
      --倒计时函数
      local function countDown()  
        ms=ms-1
        return ms
      end
    return countDown--注意返回的是函数名称 不要带括号
end 
--函数闭包
--一个函数和它所使用的所有upvalue构成了一个函数闭包

调用

timer1=createCountdownTimer(1)--创建一个倒计时器
--使用倒计时器进行三次倒计时操作
for i=1,3 do
print(timer1())
end

image-20240227114454818

Lua函数闭包和C函数的比较:

Lua函数闭包使函数具有保持其状态的能力,从此意义上来说可以与带静态局部变量的C函数来类比。

但二者有着显著的不同。

在Lua语言中函数作为一种基本数据类型–代表一种对象,可以有自己的状态;

带静态局部变量的C函数来说,它并不是C的一种数据类型,更不会产生什么对象实例,它只是一个静态地址的符号名称。

函数闭包基于对象的实现方式

函数闭包子在对象中实现,将需要隐藏的成员放到一张表中,把该表作为成员函数的upvalue

局限性:基于对象的实现不涉及继承及多态

--函数闭包在对象实例中的解读应用
--eg
 function createStudent(name,sid)  
    local data={name=name, id=sid} --data为obj.SetName,obj.GetName,obj.SetId,obj.GetId的upvalue
    local obj={}--需要隐藏的成员放在一张表格里,把表作为成员函数的upvalue
    --成员函数
    function obj.SetName(name)
        data.name=name
    end
    function obj.GetName()
        return data["name"]
        --return data.name
    end
    function obj.SetId(id)
        data.id=id
    end
    function obj.GetId()
        return data.id
    end
    return obj
end

--调用
student=createStudent("Jack",1001)
print("studentName:",student.GetName())
print("StudentId:",student.GetId())

image-20240227134522028

元表

遍历访问table,结果为空,之后便会去顺承访问元表,默认访问元表中的__index,因此会打印出 meteable中的元素。

--元表练习
function metatableFun()
    local table={}
    local metatable={a="Anny",b="and",c="Tom"}
    --metatable元表中的__index指向metatable
    setmetatable(table, {__index=metatable})
    for k,v in pairs(table) do
        print(k,"=>",v)
    end

    print("--------------------------")
    print(table.a,table.b,table.c)
end

image-20240227143124742

此处通过调用元表中的__add相关的函数,来实现两个table的相加功能。

--用于table相加运算的函数
function add(t1,t2)  
    assert(#t1==#t2)
    local size=#t1
    for i=1,size do
        t1[i]=t1[i]+t2[i]
    end
    return t1
end
function metatableFun2()
    table1=setmetatable({1,2,3},{__add=add})
    table2=setmetatable({9,8,7},{__add=add})
    --遍历table1
    for k,v in pairs(table1) do
        print(k,"=>",v)
    end
    --遍历table2
    for k,v in pairs(table2) do
        print(k,"=>",v)
    end
    print("---------table1+table2--------------")
    table1=table1+table2
    for i=1,#table1 do
        print(table1[i])
    end
end

image-20240227145655581

综上可以理解,元表本身是一个普通的表,通过特定的方法(例如setmetatable)设置到某个对象上,进而影响这个对象的行为。一个对象有哪些行为受到元表的影响以及这些行为按照何种方式收到影响是受Lua语言约束的。(例如只能根据元表中的关键字类型来设置相关的函数)元表是Lua最关键的概念之一,内容也很丰富。

--基于原型的继承
Person = {name = "Sam",sex="man"}
--构造函数
function Person:New(extension)
    local table=setmetatable(extension or{},self)
    self.__index=self --默认访问
    return table    
end

--Person 类的成员方法
function Person :SetName(name)
    self.name=name
end
function Person: SetSex(sex)
    self.sex=sex
end
function Person:GetName()
    return self.name
end
function Person:GetSex()
    return self.sex
end

--新建对象
--基于原型的继承
person=Person:New()
print("person'name:",person:GetName())
print("person'sex:",person:GetSex())
print("-------------------------------")

image-20240227153402837


补充:table作为类似键值对的数据结构时候,#获取长度为0;

且遍历时候大

![image-20240301165902701](E:\畅知-Lua学习代码文件\Lua学习笔记3.assets\image-20240301165902701.png

image-20240301170214218

posted @ 2024-03-01 17:07  畅知  阅读(29)  评论(0编辑  收藏  举报