Lua Getter&Setter 简单实现

lua 是一门简单的语言,不带类和属性封装,但可以使用 lua 强大的元表模拟实现:

1. 实现 class

local type = type
local rawset = rawset
local setmetatable = setmetatable

local traceCount = 0
local tracebacks = setmetatable({}, {__mode = "k"})

local function class(classname, super)
local cls = {}

cls.classname = classname
cls.class = cls
cls.Get = {}
cls.Set = {}

local Get = cls.Get
local Set = cls.Set

if super then
-- copy super method
for key, value in pairs(super) do
if type(value) == "function" and key ~= "ctor" then
cls[key] = value
end
end

-- copy super getter
for key, value in pairs(super.Get) do
Get[key] = value
end

-- copy super setter
for key, value in pairs(super.Set) do
Set[key] = value
end

cls.super = super
end

function cls.__index(self, key)
local func = cls[key]
if func then
return func
end

local getter = Get[key]
if getter then
return getter(self)
end

return nil
end

function cls.__newindex(self, key, value)
local setter = Set[key]
if setter then
setter(self, value or false)
return
end

if Get[key] then
assert(false, "readonly property")
end

rawset(self, key, value)
end

function cls.new(...)
local self = setmetatable({}, cls)
local function create(cls, ...)
if cls.super then
create(cls.super, ...)
end
if cls.ctor then
cls.ctor(self, ...)
end
end
create(cls, ...)

-- debug
traceCount = traceCount + 1
tracebacks[self] = traceCount

return self
end

return cls
end

return class

2. 示例 1

local class = require "class"

local Point = class("Point")

function Point:ctor(x, y)
self.x = x
self.y = y
end

function Point.Get:x() return self._x end
function Point.Set:x(value) self._x = value end

function Point.Get:y() return self._y end
function Point.Set:y(value) self._y = value end

local p = Point.new(10, 20)
print(p.x, p.y)
p.x = 5
p.y = 5
print(p.x, p.y)

3. 示例 2

local class = require "class"

local Sprite = class("Sprite")

function Sprite:ctor()self.cobj = cc.Sprite:create()
end

function Sprite.Get:x()return self.cobj:getPositionX() end
function Sprite.Set:x(value) self.cobj:setPositionX(value) end

function Sprite.Get:y()return self.cobj:getPositionY() end
function Sprite.Set:y(value) self.cobj:setPositionY(value) end

local obj = Sprite.new()
obj.x = 30
obj.y = 40

obj.y = obj.x