目錄
1、Lua面向對象基礎
面向對象三大特性包括:封裝、繼承、多態。
還有在Lua中如何創建類和實例化,這里一一介紹
1.1、Lua類的創建和實例化
Test1.lua
--name,age就相當於字段。eat就相當於方法
person = {name = 'Ffly',age = 20}
function person:eat()
print(self.name .. '該吃飯飯了,餓死了')
end
--這個方法用於實例化使用
function person:new()
local self = {}
--使用元表,並把__index賦值為person類
setmetatable(self,{__index = person})
return self
end
Test2.lua
--加載模塊Test1.lua(類似於C#中的using引用)
--LuaStudio默認從軟件根目錄下加載
require "Test1"
--實例化person類
person1 = person:new()
person1:eat() --正常輸出
1.2、Lua封裝
--對age字段進行封裝,使其只能用get方法訪問
function newPerson(initAge)
local self = {age = initAge};
--三個方法
local addAge = function(num)
self.age = self.age + num;
end
local reduceAge = function(num)
self.age = self.age - num;
end
local getAge = function(num)
return self.age;
end
--返回時只返回方法
return {
addAge = addAge,
reduceAge = reduceAge,
getAge = getAge,
}
end
person1 = newPerson(20)
--沒有使用額外的參數self,用的是那里面的self表
--所以要用.進行訪問
person1.addAge(10)
print(person1.age) --輸出nil
print(person1.getAge()) --輸出30
1.3、Lua繼承
--基類person,boy類繼承於person
person = {name = "default",age = 0}
function person:eat()
print(self.name .. '該吃飯飯了,餓死了')
end
--使用元表的 __index完成繼承(當訪問不存在的元素時,會調用)
function person:new(o)
--如果o為false或者o為nil,則讓o為{}
o = o or {}
setmetatable(o,self)
--設置上面self的__index為表person
self.__index = self
return o
end
--相當於繼承
boy = person:new()
--name在boy里找不到會去person里面找
print(boy.name) --輸出default
--修改了person里的值,並不會影響boy里面的值
boy.name = 'feifei'
print(person.name) --輸出default
print(boy.name) --輸出feifei
1.4、Lua多態
person = {name = "default",age = 0}
--重載
--簡單方法:lua中會自動去適應傳入參數的個數,所以我們可以寫在一個方法里面
function person:eat(food)
if food == nil then
print(self.name .. '該吃飯飯了,餓死了')
else
print(self.name .. '喜歡吃:' .. food)
end
end
function person:addAge(num)
if num == nil then
self.age = self.age + 1
else
self.age = self.age + num
end
end
print(person:eat())
print(person:eat("大西瓜"))
person:addAge()
print(person.age)
person:addAge(5)
print(person.age)
--重寫
function person:new(o)
--如果o為false或者o為nil,則讓o為{}
o = o or {}
setmetatable(o,self)
--設置上面self的__index為表person
self.__index = self
return o
end
boy = person:new()
boy.name = "Ffly"
boy:eat() --調用基類eat方法
--相當於重寫eat方法
function boy:eat()
print('小男孩' .. self.name .. '快要餓死了')
end
boy:eat() --調用派生類eat方法
2、Lua面向對象進階
2.1、class.lua的實現
class代碼參考於雲風大大的博客。
class.lua
--表_class的key為類,value為類的虛表
local _class={}
--為什么要使用虛表呢?
--[[
使用虛表的話,那么類本身的元素會是穩定的,
所有的變化都在虛表中進行,
這樣 封裝了變化、也便於繼承的實現
]]
function class(super)
--要創建的類class_type
local class_type={}
--構造函數,基類
class_type.ctor=false
class_type.super=super
--class_type類型的虛表,虛表中包含class_type中的元素
local vtb1={}
_class[class_type]=vtb1
--給類設置元表
--在給表添加新元素時,會在虛表中也添加
setmetatable(class_type,{
__newindex = function(t,k,v) vtb1[k] = v end,
__index = function(t,k) return vtb1[k] end,
})
--super不為空,表示為繼承
if super then
setmetatable(vtb1,{__index=
function(t,k)
--從基類找要找的元素,找到就放入派生類虛表中
local ret=_class[super][k]
vtb1[k]=ret
return ret
end
})
end
--給類型class_type創建實例對象
--1、先依次從最頂層基類中調用構造方法
--2、然后設置元表
class_type.new=function(...)
--生成這個類對象
local obj={}
do
local create
--遞歸調用構造函數
create = function(c,...)
--super不為空,表示有基類
if c.super then
create(c.super,...)
end
--調用構造函數
if c.ctor then
c.ctor(obj,...)
end
end
create(class_type,...)
end
--設置obj的 __index為class_type的虛表
setmetatable(obj,{ __index=_class[class_type] })
return obj
end
return class_type
end
person.lua
require "class"
--創建基類person
person = class()
person.name = "Ffly"
person.age = 20
--設置person類的構造函數
function person:ctor()
print("person:ctor 調用");
end
function person:eat()
print(self.name .. "很餓,想吃東西")
end
--創建派生類boy,基類為person
boy = class(person)
function boy:ctor()
print("boy:ctor 調用");
end
function boy:eat()
print("boy " .. self.name .. "很餓,想吃東西")
end
--創建完兩個類后,就可以使用了。
--創建boy類的實例boy1
boy1 = boy.new()
boy1:eat()
--[[
輸出:
person:ctor 調用
boy:ctor 調用
boy Ffly很餓,想吃東西
]]
2.2、單例模式的實現
Boy.lua
require "class"
boy = class()
--單例模式的實現
boy.Instance = function()
if (nil == boy.m_instance) then
boy.m_instance = boy.new();
end
return boy.m_instance
end
function boy:ctor()
end
Singleton.lua
require "boy"
local b1 = boy.Instance()
local b2 = boy.Instance()
if b1==b2 then
print("相等")
else
print("不相等")
end
--輸出相等