[Unity热更新]lua基础(四)

九.面向对象编程

在lua中,可以使用table来表示"类":

--基类Account
--定义变量balance
--定义方法new,deposit,withdraw
--self是lua的关键字,类似于this,指调用者本身,如Account:new,self就是指Account;如a:deposit,self就是指a
--Account:deposit(v)的另一种写法为:Account.deposit(self, v)
--调用时,就要写成:a.deposit(a, v)的形式

Account = {balance = 0}              --设置balance默认值为0

function Account:new(o)              --构造函数,名字可随意取
	o = o or {}                      --若o为nil,则创建一个table
	setmetatable(o,self)             --设置o的元表为self,当调用Account:new时,self等于Account
	self.__index = self              --当在o中找不到key时,lua会找元表中__index对应的函数或者table
	return o
end

function Account:deposit(v)
	self.balance = self.balance + v
end

function Account:withdraw(v)
	if v > self.balance then
		error "insufficient funds"
	else
		self.balance = self.balance - v
	end
end

----------------------------------------------------------------

a = Account:new({balance = 200})
a:deposit(100)                     --a没有deposit字段,所以会使用Account的deposit方法
print(a.balance)                   --300

b = Account:new()
print(b.balance)                   --0

c = b:new({limit = 1000})          --b从Account中继承了new,而b中的new方法,self代表的是b
--因此,c的元表为b,b中的__index字段为b,c继承b,b继承Acount
c:deposit(500)
print(c.balance)                   --500

----------------------------------------------------------------

--[[
b可以重写从Acount中继承的方法
]]

function b:getLimit()
	return self.limit or 0
end

function b:withdraw(v)
	if v - self.balance >= self:getLimit() then
		error "insufficient funds"
	else
		self.balance = self.balance - v
	end
end

c:withdraw(700)                     --c会先从b中找withdraw
print(c.balance)                    -- -200
print(c:getLimit())                 --1000
 
----------------------------------------------------------------

function c:getLimit()
	return self.balance * 0.1
end

print(c:getLimit())                 -- -20


十.模块与包

require的使用

1.使用的编辑器是LuaEditor(v6.30),需要设置选项 / 编译调试设置,先取消勾选"直接以xxx",然后设置脚本工作目录(即lua脚本的目录),最后重新勾选"直接以xxx"

2.在桌面新建一个文件夹,然后如图,然后在another下建一个Test2.lua


3.

--Test.lua
print("Test");  
function hehe()  
    print("hello");  
end  


--Test2.lua
print("Test2");  
function hehe()  
    print("hello2");  
end  


--TestRequire.lua
print(package.path)      --输出默认的搜索模式      
require("Test") 
package.path=package.path..";.\\another\\?.lua;"
require("Test2") 
require("Test")          --不再执行


以我的为例,打印的package.path是(package.path是lua内置的东西,可以看作为搜索文件的模式):

.\?.lua;D:\Program Files\LuaEditor6.30\lua\?.lua;后面略,其中分号是分隔符

当require("Test")时,lua会用Test来替代上面的问号,从而变成:

.\Test.lua;D:\Program Files\LuaEditor6.30\lua\Test.lua;

意思就是从当前目录、D:\Program Files\LuaEditor6.30\lua等路径逐一搜索Test.lua这个文件

其中require会在初次加载时执行一次该lua文件,require第二次时,是不会再加载的


相对路径:

";.\\another\\?.lua;"     .\的意思是当前目录,..\是上一层目录

绝对路径:

package.path=package.path..";D:\?.lua;"


4.编写模块

--LuaEditor1.lua

local M = {}
--complex是供外部调用的接口,M是内部table,当修改接口名时
--只需修改complex和return,内部的函数定义就不需修改了
complex = M

function M.new(r,i)  
	return {r=r,i=i}
end

M.i = M.new(0,1)

function M.add(c1,c2)
	return M.new(c1.r+c2.r, c1.i+c2.i)
end

function M.sub(c1,c2)
	return M.new(c1.r-c2.r, c1.i-c2.i)
end

function M.mul(c1,c2)
	return M.new(c1.r*c2.r, c1.i*c2.i)
end

function M.div(c1,c2)
	return M.new(c1.r/c2.r, c1.i/c2.i+M.inv(1))
end

function M.inv(c)
	local n = c + 1;
	return n
end

--如果没有返回值,默认会返回一个布尔类型,表示该模块是否加载过
return complex

local o = require "LuaEditor1"
a = o.new(1,2);
b = o.new(3,4);
print(o.add(a,b).r..","..o.add(a,b).i);
print(o.div(a,b).r..","..o.div(a,b).i);

print(complex.new(10,20).i);--]]









你可能感兴趣的:(lua)