23、Lua 学习笔记之一(初阶话题)

发布于:2024-04-19 ⋅ 阅读:(28) ⋅ 点赞:(0)

前言

本文针对的读者是有经验的C/C++程序员,希望了解Lua或者迅速抓住Lua的关键概念和模式进行开发的。因此本文并不打算教给读者条件语句的语法或者函数定义的方式等等显而易见的东西,以及一些诸如变量、函数等编程语言的基本概念。本文只打算告诉读者Lua那些与C/C++显著不同的东西以及它们实际上带来了怎样不同于C/C++的思考方式。不要小看它们,它们即将颠覆你传统的C/C++的世界观!

本文一共分初阶、进阶和高阶三大部分,每个部分又有若干章节。读者应当从头至尾循序渐进的阅读,但是标有“*”号的章节(主要讨论OO在Lua中的实现方式)可以略去而不影响对后面内容的理解。读者只要把前两部分完成就可以胜任Lua开发的绝大部分任务。高阶部分可作为选择。

初阶话题

八种基本类型

基本类型 描述 备注
数值(number) 内部以double表示
字符串(string) 总是以零结尾,但可以包含任意字符(包括零),因此并不等价于C字符串, 而是其超集
布尔(boolean) 只有“true”或者“false”两个值。
函数(function) Lua的关键概念之一。不简单等同于C的函数或函数指针。
表(table) 异构的Hash表。Lua的关键概念之一。
userdata 用户(非脚本用户)定义的C数据结构。脚本用户只能使用它,不能定义。
线程(thread) Lua协作线程(coroutine),与一般操作系统的抢占式线程不一样。
nil 代表什么也没有,可以与C的NULL作类比,但它不是空指针。

函数

实例代码

function foo(a, b, c, ...)
    local sum = a + b
    return sum, c --函数可以返回多个值
end
r1, r2 = foo(1, "123", "hello") --平行赋值 print(r1,r2);

输出结果

124hello

函数基本使用方法

  • 函数定义
    用关键字function定义函数,以关键字end结束

  • 局部变量
    用关键字local定义。如果没有用local定义,即使在函数内部定义的变量也是全局变量

  • 函数可以返回多个值
    return a, b, c, …

  • 平行赋值
    a,b = c, d

  • 全局变量
    前面的代码定义了三个全局变量:foo、r1和r2

实例代码

local a = {}
    local b = {x = 1,["hello,"] = "world!"}
    a["astring"] = "ni,hao!"
    a[1] = 100
    a["a table"] = b

    for k,v in  pairs(a) do
        print(k,"=>",v);
    end

输出结果

1=>100

astring=>ni,hao!

atable=>table: 0xfd59570

表使用方法

  • 定义表(Table)的方式
    a={}, b = {…}

  • 访问表的成员
    通过 . 或者 [] 运算符来访问表的成员。
    注意:表达式a.b等价于a[b],但不等价于a[b]

  • 表项的键和值
    任何类型的变量,除了nil,都可以做为表项的键。从简单的数值、字符串到复杂的函数、表等等都可以;同样,任何类型的变量,除了nil,都可以作为表项的值。给一个表项的值赋nil意味着从表中删除这一项,比如令a.b= nil,则把表a中键为b的项删除。如果访问一个不存在的表项,其值也是nil,比如有c = a.b,但表a中没有键为b的项,则c等于nil

一种简单的对象实现方式

实现代码

function create(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

    local myCreate = create("sam",001)

    for k,v in pairs(myCreate) do
        print(k,"=>",v)
    end

    print("myCreate's name:",myCreate:GetName(),"myCreate's id:",myCreate.GetId(myCreate))

    myCreate:SetId(100)
    myCreate:SetName("Hello Kity")

    print("myCreate's name:",myCreate:GetName(),"myCreate's id:",myCreate:GetId())

输出结果

SetName=>function: 0x85efc50

GetId=>function: 0x85efc10

id=>1

SetId=>function: 0x85efd00

GetName=>function: 0x85efce0

name=>sam

myCreate’s name:sammyCreate’s id:1

myCreate’s name:Hello KitymyCreate’s id:100

对象实现描述

  • 对象工厂模式
    如前面代码的create函数

  • 用表来表示对象
    把对象的数据和方法都放在一张表内,虽然没有隐藏私有成员,但对于简单脚本来说完全可以接受。

  • 成员方法的定义
    function obj:method(a1, a2, …) … end 等价于function obj.method(self, a1, a2, …) … end 等价于obj.method = function (self, a1, a2, …) … end

  • 成员方法的调用
    obj:method(a1, a2, …) 等价于obj.method(obj, a1, a2, …)

简单继承

实现代码

 local 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
local function createFootballRobot(name, id, position)
    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
local mycreateFootballRobot = createFootballRobot("Tom", 1000, "广州")
print(
    "mycreateFootballRobot's name:",
    mycreateFootballRobot:GetName(),
    "myCreate's id:",
    mycreateFootballRobot:GetId(),
    mycreateFootballRobot:GetPosition()
)
mycreateFootballRobot:SetName("麦迪")
mycreateFootballRobot:SetId(2000)
mycreateFootballRobot:SetPosition("北京")
print(
    "mycreateFootballRobot's name:",
    mycreateFootballRobot:GetName(),
    "myCreate's id:",
    mycreateFootballRobot:GetId(),
    mycreateFootballRobot:GetPosition()
)

输出结果

mycreateFootballRobot’s name:TommyCreate’s id:1000right back
mycreateFootballRobot’s name:麦迪myCreate’s id:2000北京

简单继承优缺点

  • 优点:
    简单、直观
  • 缺点:
    传统、不够动态

参考文献《C/C++程序员的Lua快速入门》