美文网首页
lua实现class(面向对象)

lua实现class(面向对象)

作者: 小血Blood | 来源:发表于2020-05-20 17:50 被阅读0次

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

    相关文章

      网友评论

          本文标题:lua实现class(面向对象)

          本文链接:https://www.haomeiwen.com/subject/navnohtx.html