Lua中面向對象編程的理解
模塊
模塊是一個獨立的空間,一個獨立的環境,訪問模塊成員需要先require,並使用“模塊名.成員名稱”的格式訪問。注意:模塊是一個table。
類
在lua中所有對象都是一個table,類也是一個table,但類應該是一個只讀的table,類的定義是通過創建一個模塊實現的。
lua代碼:
module("Student",package.seeall)
function study(self)
end
在調用module方法時添加package.seeall參數的作用是:讓該模塊可以訪問全局變量。
對象
對象是一個類的實例,在Lua中對象是一個table,在Lua中類更像是一個原型(一個只讀的對象)。
通過設置tableA的元表的__index字段為tableB,當讀tableA中沒有的字段時就會從tableB中讀該字段。
可以先創建一個空table,然後通過設置元表的方式,創建一個對象,當訪問該對象沒有的字段時就會在類中尋找。
lua代碼:
-- 創建對象方法
function new( moduleName )
local obj = {}
setmetatable(obj,{__index = moduleName})
return obj
end
繼承
在Lua中繼承也可以通過設置元表的方式實現。
lua代碼:
-- 繼承
function extend( child, parent )
setmetatable(child,{__index = parent})
end
靜態與非靜態
靜態成員與非靜態成員的區別就在於:是否可以通過類名訪問,如果可以通過類名訪問則是公有靜態成員,否則是非公有靜態成員或非靜態成員。而在Lua中類名就是模塊名稱,如果可以“模塊名.成員名”形式訪問則是公有靜態成員。
lua代碼:
module("Student",package.seeall)
-- 公有靜態成員變量(可通過模塊名訪問)
flag = 1
-- 私有靜態成員變量(外部不可訪問)
local flag2 = 2
-- 非靜態成員方法(需要傳self)
function init(self, name)
-- 非靜態成員變量
self.name = name
end
-- 靜態成員方法(不需要傳self)
function getFlag()
return flag
end
-- 非靜態成員方法
function getName(self)
return self.name
end
tools.lua
-- 創建一個對象並初始化
function create( moduleName, ... )
local obj = new(moduleName)
obj:init( ... )
return obj
end
調用代碼:
require "utils/tools"
require "Student"
-- 訪問公有靜態成員變量
cclog("flag = %d",Student.flag)
-- 訪問靜態方法
cclog("flag = %d",Student.getFlag())
-- 創建一個Student對象
local obj = create(Student,"xiaoming")
-- 通過對象訪問公有靜態成員變量
cclog("falg = %d",obj.flag)
-- 訪問非靜態成員變量
cclog("name = %s",obj.name)
-- 訪問非靜態成員方法
cclog("name = %s",obj:getName())
打印結果:
1.靜態成員變量與非靜態成員變量的區別在於:該變量是存在模塊的環境中,還是存在self中。
2.靜態成員方法與非靜態成員方法的區別在於:該方法是否需要傳self。
3.訪問靜態成員與非靜態成員
訪問模塊中的成員都可以通過“模塊名.成員名稱”的方式訪問,但訪問模塊中非靜態成員方法時,通過“self:成員名稱()”的方式會更方便(注意:":"只是為了語法便利,作用只是把self作為方法的第一個實參,與“模塊名稱.(self)”沒什麼區別)。
注意:在Lua中本來並沒有靜態與非靜態這個概念。