LUA面向对象程序设计(四)多重继承

来源:互联网 发布:台州学院网络教学平台 编辑:程序博客网 时间:2024/05/14 02:29

 

在Lua中实现多重继承,可以有多种方案,在pil中,lua作者提供了一种实现多种继承的方案,但我个人认为,这种方案虽然简洁,但并不算得优雅。后来云风(江湖传说很流弊的人)给出了另外一种既简洁又不失优雅的解决方案,其实现方案,深刻把握了oo的思想。但是,风云(我觉得比云风顺口多了-:-)的实现并没有考虑多重继承的情况,在这里,在风云的实现方案的基础上加以扩展,以支持多种继承的情况。

 

下面先来看看风云的实现:

 

local _class={} function class(super)local class_type={}class_type.ctor=falseclass_type.super=superclass_type.new=function(...) local obj={}dolocal createcreate = function(c,...)if c.super thencreate(c.super,...)endif c.ctor thenc.ctor(obj,...)endend create(class_type,...)endsetmetatable(obj,{ __index=_class[class_type] })return objendlocal vtbl={}_class[class_type]=vtbl setmetatable(class_type,{__newindex=function(t,k,v)vtbl[k]=vend}) if super thensetmetatable(vtbl,{__index=function(t,k)local ret=_class[super][k]vtbl[k]=retreturn retend})end return class_typeend


 

通过上面的函数class,就可以方便地在lua中定义一个类了:

 

base_type=class()       -- 定义一个基类 base_typefunction base_type:ctor(x)  -- 定义 base_type 的构造函数    print("base_type ctor")    self.x=xendfunction base_type:print_x()    -- 定义一个成员函数 base_type:print_x    print(self.x)endfunction base_type:hello()  -- 定义另一个成员函数 base_type:hello    print("hello base_type")end

 

 

通过下面的方式就可以实现单一的继承:

child=class(base_type) -- 定义一个类 child 继承于 base_type

 

function child:ctor()    -- 定义 child 的构造函数    print("child ctor")endfunction child:hello()   -- 重载 base_type:hello 为 child:hello    print("hello child")end

 

 

现在就创建一个child类的一个实例:

obj = child.new(1)   -- 输出两行,base_type ctor 和 child ctor 。这个对象被正确的构造了。obj:print_x() -- 输出 1 ,这个是基类 base_type 中的成员函数。obj:hello()   -- 输出 hello child ,这个函数被重载了。

 

 

如果想实现多层单一继承,可以继续创建一个类child2,继承于child,这样就可以实现三层的单一继承了。这里class函数只接收小于等于1个参数的情况,想通过上面的class函数实现多重继承,没有办法实现,但是可以在其基础上加以修改以实现之。

 

主要修改点有:

>将class的参数修改为可变参数,这样便可以接收任意个参数

>需要递归遍历子类的所有父类,然后执行相应的动作

 

修改后的class代码如下:

 

local _class={}
 
function class(...)
local cls = {}

cls.ctor = false       --是否存在构造函数
cls.__base = {...}      --当前类的基类们,可能一个,可能多个,可能没有
 
cls.new = function(...) 
    local obj = {}
    do
        local create
        create = function(c,...)
            if c.__base then
                for _, k in pairs(c.__base) do
                    create(k, ...)
                end

            end
            if c.ctor then
                c.ctor(obj, ...)
            end
        end
        create(cls,...)
    end


    setmetatable(obj, { __index=_class[cls] })
    return obj
end


local vtbl={}
_class[cls]=vtbl
 
setmetatable(cls, {__newindex=
    function(t, k, v)
        vtbl[k] = v

    end
})
 
if cls.__base then
    setmetatable(vtbl, {__index =
        function(tab, key)
            for _, base_cls in pairs(cls.__base) do
                local ret = _class[base_cls][key]
                     if ret then
                         vtbl[key] = ret
                         return ret
                     end
           end
    
           return nil
        end
    })
end
 
return cls
end

 

下面来验证一下,首先我们创建两个基类Name和Account:

 

Name = class()

function Name:ctor()
    print("Name ctor")
    self.name = "Smith"
end

function Name:getName()
    print("Your name: ".. self.name)
end

 

Account = class()

function Account:ctor()
    print("Account ctor")
    self.balce = 1000
end

function Account:deposit(v)
    self.balce = self.balce + v
end

function Account:getBalance()
    print(self.balce)
end

function Account:withdraw(v)
    if self.balce < v then
         print(string.format("your account remains %d, not enough %d", self.balce, v))
         return
    end
    self.balce = self.balce - v
end

 

接下来创建一个子类SpecialAccount,继承上面的两个基类:

 

SpecialAccount = class(Name, Account)
function SpecialAccount:ctor()
    print("SpecialAccount ctor")
end

 

创建SpecialAccount类的一个实例,并调用其继承的基类的相关接口:

 

sc = SpecialAccount.new()

sc:getName()
sc:getBalance()

 

输出结果:

Name ctor

Account ctor

SpecialAccount ctor

Your name: Smith

1000

 

说明SpecialAccount的对象已经被正确构造了,并且继承了其父类的方法。但是上述的实现仍然存在一点点的瑕疵,比如在子类的函数中不能调用其父类的同名函数,mywcyfl给出了一种解决方案,可以参考一下;还有另一个问题就是在多层继承中,如果给子类的new方法传递参数,那么该参数也会用于父类中的参数的初始化,我也不确定这是否合理。

 

(全文完)

0 0