zoukankan      html  css  js  c++  java
  • 在 slua 中使用更新的面向对象方案

      上一篇记录了我使用 Slua.Class 来实现面向对象扩展 C# 中得类,但实际使用中,更多地情况是直接在 lua 中定义基类然后扩展,于是触发了我重新思考下是否两种形式应该统一用一种,目前的方案中,有一个不好的地方是,每一个派生类的实例,其实内部会有多个实例(每一个继承的类都有个对应的实例,参考 __call 的调用),所以继承层次越深,内部的实例越多,而这些父类的实例仅仅是提供了属性和方法而已,没有其它作用,这其实造成了一种浪费,但如果改动的话,我想整个结构和基础都得该,影响了本身 slua 中代码的兼容性。

      我仔细阅读了云风给出的 lua oop 方案,方法够精简,确实也解决了我想解决的问题,所有的类对象,都只有一个实例,他们查询父类的方法和属性,都通过缓存的 table 来查询,避免了浪费。但对于我个人目前的需求来讲,还有些不足:

    1. 包装的过于严实,无法直接使用 类名.静态方法名 来使用静态方法;
    2. 无法直接使用 super 关键字来访问父类方法,这样只能强制你完全重写继承的方法;(而关于我修改的 slua 中的 通过 __base 访问父类的机制,其实有缺陷,因为 只能通过 self.__base.Method(self, ...),但是 super 应该隶属于类而不是对象,应该 NewCls.__base.Method(self, ...) 这样才对。),修改完应该每个派生类会多一个实例用来指向 super 的父类访问,而这个类是共享的,所以开销可以忽略不计;
    3. 为了整体代码风格统一(提供同 Slua.Class 继承类同样的实例化类方法),我需要也添加一个默认实例化方法: local obj = NewCls(...),等同于 local obj = NewCls.new(...)。

      修改完的代码如下(请忽略我修改了变量名):

    -- The hold all class type.
    local __TxClassTypeList = {}
    
    -- The inherit class function.
    local function TxClass(SuperType)
        -- Create new class type.
        local ClassType = {}
        ClassType.Ctor = false
        ClassType.SuperType = SuperType
    
        -- Create new class instance function.
        local function ClassTypeInstance(...)
            local Obj = {}
                do
                    local Create
                    Create = function (c, ...)
                        if c.SuperType then
                            Create(c.SuperType, ...)
                        end
    
                        if c.Ctor then
                            c.Ctor(Obj, ...)
                        end
                    end
     
                    Create(ClassType, ...)
                end
    
                setmetatable(Obj, {__index = __TxClassTypeList[ClassType]})
                return Obj
        end
    
        -- The new function of this class.
        ClassType.new = ClassTypeInstance
    
        -- The super class type of this class.
        if SuperType then
            ClassType.super = setmetatable({}, 
            {
                __index = function (t, k)
                    local Func = __TxClassTypeList[SuperType][k]
                    if "function" == type(Func) then
                        t[k] = Func
                        return Func
                    else
                        error("Accessing super class field are not allowed!")
                    end
                end
            })
        end
    
        -- Virtual table
        local Vtbl = {}
        __TxClassTypeList[ClassType] = Vtbl
     
        -- Set index and new index of ClassType, and provide a default create method.
        setmetatable(ClassType,
        {
            __index = function (t, k)
                return Vtbl[k]
            end,
    
            __newindex = function (t, k, v)
                Vtbl[k] = v
            end,
    
            __call = function (self, ...)
                return ClassTypeInstance(...)
            end
        })
     
        -- To copy super class things that this class not have.
        if SuperType then
            setmetatable(Vtbl,
            {
                __index = function (t, k)
                    local Ret = __TxClassTypeList[SuperType][k]
                    Vtbl[k] = Ret
                    return Ret
                end
            })
        end
     
        return ClassType
    end

      现在我可以如下使用:

    -- Base class.
    local BaseFoo = TxClass()
    
    BaseFoo.Name = "I am BaseFoo!"
    
    function BaseFoo:Ctor()
        print("BaseFoo in constructor.")
    end
    
    function BaseFoo.PrintHello()
        print("Hello BaseFoo!")
    end
    
    function BaseFoo:Foo()
        print("Name is: " .. self.Name)
    end
    
    -- Derived class.
    local MyFoo = TxClass(BaseFoo)
    
    MyFoo.Age = 18
    
    function MyFoo:Ctor()
        print("MyFoo in constructor.")
    end
    
    function MyFoo:Foo()
        MyFoo.super.Foo(self)
        print("Age is: " .. tostring(self.Age))
    end
    
    -- Create instance.
    local bf = BaseFoo.new()
    bf:Foo()
    
    local mf = MyFoo()
    mf:Foo()
    
    BaseFoo.PrintHello()
    MyFoo.PrintHello()

       接下来如云风所说,我应该思考下如何实现 Destructor。

     
  • 相关阅读:
    emberjs初学记要
    自我的一点介绍(七夕礼物)
    JavaScript数据类型
    Vue+Webpack项目配置
    Git知识点整合
    Log4j简单配置解析
    如何明智地向程序员提问
    Navicat连接mysql报错1251
    多表查询sql语句
    PLSQL面向对象
  • 原文地址:https://www.cnblogs.com/yaukey/p/4547882.html
Copyright © 2011-2022 走看看