对象
-- 元类
Shape = {area = 0}
-- 基础类方法 new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- 基础类方法 printArea
function Shape:printArea ()
print("面积为 ",self.area)
end
-- 创建对象
myshape = Shape:new(nil,10)
myshape:printArea()
output
面积为 100
继承
-- Meta class
Shape = {area = 0}
-- 基础类方法 new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- 基础类方法 printArea
function Shape:printArea ()
print("面积为 ",self.area)
end
-- 创建对象
myshape = Shape:new(nil,10)
myshape:printArea()
Square = Shape:new()
-- 派生类方法 new
function Square:new (o,side)
o = o or Shape:new(o,side)
setmetatable(o, self)
self.__index = self
return o
end
-- 派生类方法 printArea
function Square:printArea ()
print("正方形面积为 ",self.area)
end
-- 创建对象
mysquare = Square:new(nil,10)
mysquare:printArea()
Rectangle = Shape:new()
-- 派生类方法 new
function Rectangle:new (o,length,breadth)
o = o or Shape:new(o)
setmetatable(o, self)
self.__index = self
self.area = length * breadth
return o
end
-- 派生类方法 printArea
function Rectangle:printArea ()
print("矩形面积为 ",self.area)
end
-- 创建对象
myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()
output
面积为 100
正方形面积为 100
矩形面积为 200
完整代码
local type = type
local rawget = rawget
local getmetatable = getmetatable
local setmetatable = setmetatable
-- set metatable's __index of t
local setmetatableindex = function(t, index)
local mt = getmetatable(t)
if not mt then
mt = {}
end
if not mt.__index then
mt.__index = index
setmetatable(t, mt)
elseif mt.__index ~= index then
setmetatableindex(mt, index)
end
end
-- class is kind of cname
local iskindof_
iskindof_ = function(cls, cname)
local __index = rawget(cls, "__index")
if type(__index) == "table" and rawget(__index, "__cname") == cname then
return true
end
if rawget(cls, "__cname") == cname then
return true
end
local __supers = rawget(cls, "__supers")
if not __index then
return false
end
for _, super in ipairs(__supers) do
if iskindof_(super, cname) then
return true
end
end
return false
end
function iskindof(obj, cname)
local t = type(obj)
if t ~= "table" and t ~= "userdata" then
return false
end
local mt = getmetatable(obj)
if mt then
if iskindof_(mt, cname) then
return true
elseif mt.class and iskindof_(mt.class, cname) then
return true
end
end
return false
end
function class(classname, ...)
if not classname or type(classname) == "table" then
assert(false, "error class definition!")
end
local cls = {__cname = classname}
local supers = {...}
for _, super in ipairs(supers) do
local superType = type(super)
assert(
superType == "nil" or superType == "table",
string.format('class() - create class "%s" with invalid super class type "%s"', classname, superType)
)
if superType == "table" then
cls.__supers = cls.__supers or {}
cls.__supers[#cls.__supers + 1] = super
if not cls.super then
-- set first super pure lua class as class.super
cls.super = super
end
else
error(string.format('class() - create class "%s" with invalid super type', classname), 0)
end
end
cls.__index = cls
if not cls.__supers or #cls.__supers == 1 then
setmetatable(cls, {__index = cls.super})
else
setmetatable(
cls,
{
__index = function(_, key)
local supers = cls.__supers
for i = 1, #supers do
local super = supers[i]
if super[key] then
return super[key]
end
end
end
}
)
end
if not cls.ctor then
-- add default constructor
cls.ctor = function()
end
end
cls.new = function(...)
local instance = {}
setmetatableindex(instance, cls)
instance.class = cls
instance:ctor(...)
return instance
end
cls.is = function(obj, cls)
if not obj or not cls then
return false
end
local __index = rawget(cls, "__index")
local cname = rawget(__index, "__cname")
return iskindof(obj, cname)
end
return cls
end