用惯了python,觉得python真的好写。相比起来lua简直是一坨屎。
拿lua开发的话,面向对象还是必不可少的。虽然网上各种实现都有了,但是用起来都不是特别顺手。
于是来造个轮子,仿照python中的一些语法和使用习惯,写了个class.lua。
直接上代码:
-- utils.lua
string.split = function (fullstring, separator)
local find_start_index = 1
local split_index = 1
local ret = {}
while true do
local find_last_index = string.find(fullstring, separator, find_start_index)
if not find_last_index then
ret[split_index] = string.sub(fullstring, find_start_index, string.len(fullstring))
break
end
ret[split_index] = string.sub(fullstring, find_start_index, find_last_index - 1)
find_start_index = find_last_index + string.len(separator)
split_index = split_index + 1
end
return ret
end
function rawtostring(t)
local metatable = getmetatable(t)
if metatable then
if metatable.__tostring then
local tmp = metatable.__tostring
metatable.__tostring = nil
local ret = tostring(t)
metatable.__tostring = tmp
return ret
end
end
return tostring(t)
end
function topointer(t)
local ttype = type(t)
if ttype == "function" or ttype == "table" then
local strs = rawtostring(t):split(": ")
return strs[2]
end
return nil
end
-- class.lua
require "utils"
local Class = {
__name__ = "Class",
}
Class.__class__ = Class
local MetaClass = { }
MetaClass.__tostring = function (obj)
return string.format( "<class \"%s\">", obj.__name__)
end
MetaClass.__call = function (_, name, base)
local class_type = {
__class__ = Class,
__name__ = name,
__super__ = base,
}
local class_object_meta = {
__index = class_type,
__tostring = function (obj)
return string.format( "<%s Object>: %s", obj.__class__.__name__, topointer(obj))
end
}
local class_type_meta = {
__tostring = function (cls)
return string.format( "<class \"%s\">: %s", cls.__name__, topointer(cls))
end,
__call = function (cls, ...)
local object = {
__class__ = class_type
}
setmetatable(object, class_object_meta)
if object.__init__ then
object.__init__(object, ...)
end
return object
end
}
if class_type.__super__ then
class_type_meta.__index = class_type.__super__
end
setmetatable(class_type, class_type_meta)
return class_type
end
setmetatable(Class, MetaClass)
Class.super = function (class)
return class.__super__
end
return Class
然后看如何使用:
local class = require "class"
local super = class.super
local Foo = class("Foo")
function Foo:Echo()
print(self.msg)
end
-- Foo类,无初始化方法,有一个Echo方法
local Bar = class("Bar", Foo)
function Bar:__init__(msg)
print "Bar Init Call"
self.msg = msg
end
-- Bar类,继承自Foo,有初始化方法
local Foobar = class("Foobar", Bar)
function Foobar:__init__(msg, count) -- 重写了初始化方法
super(Foobar).__init__(self, msg) -- 并且用super方法拿到父类的初始化方法并调用。用过python的应该很熟悉这种用法。
self.count = count
end
function Foobar:Echo()
for i=1, self.count do
super(Foobar).Echo(self)
-- 另一种写法 self.__super__.Echo(self)
end
end
-- Foobar类,继承自Bar,重写了初始化方法,和Echo方法
local obj = Foobar("哈哈", 2)
obj:Echo()
print(obj)
print(obj.__class__)
print(obj.__class__.__super__)
print(obj.__class__.__super__.__super__)
print(obj.__super__.__init__)
print(obj.__class__ == Foobar)
print(obj.__super__ == super(Foobar))
print(super(Foobar) == Bar)
输入:
Bar Init Call
哈哈
哈哈
<Foobar Object>: 0000028788634A80
<class "Foobar">: 0000028788635000
<class "Bar">: 00000287886352C0
<class "Foo">: 0000028788635800
function: 000002878682E660
true
true
true
如果用过python的对这个用法应该感到很亲切吧。
然后就是一些拓展性的东西,比如用self.__class__ == T
来判断某个obj是否是一个类的实例,用c.__class__ == class
来判断一个变量是否是一个Class,也可以利用__super__
,实现一个方法issubclass(c, base)
来判断某个c是否继承自base,实现isinstance(obj, c)
判断obj是否是继承自c的实例。
网友评论