用慣了python玖翅,覺得python真的好寫。相比起來lua簡直是一坨屎凌节。
拿lua開發(fā)的話,面向對象還是必不可少的椿争。雖然網上各種實現(xiàn)都有了,但是用起來都不是特別順手秘遏。
于是來造個輪子丘薛,仿照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__
,實現(xiàn)一個方法issubclass(c, base)
來判斷某個c是否繼承自base殿如,實現(xiàn)isinstance(obj, c)
判斷obj是否是繼承自c的實例贡珊。