lua实现class(面向对象)

用惯了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的实例。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352