lua實現(xiàn)class(面向對象)

用慣了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的實例贡珊。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市涉馁,隨后出現(xiàn)的幾起案子门岔,更是在濱河造成了極大的恐慌,老刑警劉巖烤送,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寒随,死亡現(xiàn)場離奇詭異,居然都是意外死亡帮坚,警方通過查閱死者的電腦和手機牢裳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叶沛,“玉大人蒲讯,你說我怎么就攤上這事』沂穑” “怎么了判帮?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵局嘁,是天一觀的道長。 經常有香客問我晦墙,道長悦昵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任晌畅,我火速辦了婚禮但指,結果婚禮上,老公的妹妹穿的比我還像新娘抗楔。我一直安慰自己棋凳,他們只是感情好,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布连躏。 她就那樣靜靜地躺著剩岳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪入热。 梳的紋絲不亂的頭發(fā)上拍棕,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天,我揣著相機與錄音勺良,去河邊找鬼。 笑死尚困,一個胖子當著我的面吹牛尾组,可吹牛的內容都是我干的忙芒。 我是一名探鬼主播示弓,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼跨跨!你這毒婦竟也來了?” 一聲冷哼從身側響起囱皿,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤勇婴,失蹤者是張志新(化名)和其女友劉穎嘱腥,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體橱脸,經...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡添诉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蘑斧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片须眷。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡柒爸,死狀恐怖,靈堂內的尸體忽然破棺而出乐横,到底是詐尸還是另有隱情今野,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布催什,位于F島的核電站蒲凶,受9級特大地震影響拆内,放射性物質發(fā)生泄漏。R本人自食惡果不足惜麸恍,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一抹沪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧敏弃,春花似錦噪馏、人聲如沸虹茶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至欢搜,卻和暖如春谴轮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疮装。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工廓推, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翩隧,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓专缠,卻偏偏與公主長得像淑仆,于是被迫代替她去往敵國和親糯景。 傳聞我的和親對象是個殘疾皇子省骂,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355