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方法传递参数,那么该参数也会用于父类中的参数的初始化,我也不确定这是否合理。
(全文完)
- LUA面向对象程序设计(四)多重继承
- LUA面向对象程序设计(二)继承
- Lua面向对象 -- 多重继承、私密性
- 《Lua 程序设计》-16.3多重继承
- 面向对象的程序设计学习笔记3-多重继承
- Lua面向对象程序设计
- LUA面向对象程序设计(一)类
- LUA面向对象程序设计(三)多态
- Lua:table对象、类、继承、多重继承
- 面向对象程序设计(四)
- 面向对象程序设计(多态、转换、继承)
- lua 类, 继承, 面向对象
- lua 类, 继承, 面向对象
- lua 类, 继承, 面向对象
- Lua 之 面向对象 -- 继承
- lua面向对象、继承、多态
- [Lua]Lua的面向对象程序设计
- java面向对象程序设计(四)
- LUA面向对象程序设计(三)多态
- JS,判断对象是否具有指定的方法?
- Android控件之HorizontalScrollView代替Gallery
- 希尔排序
- HDU2082
- LUA面向对象程序设计(四)多重继承
- 雷德为您展现立式锯床的特色
- C++多态性1
- Java Web开发简介(章节摘要)
- Ubuntu 14.04 LTS下安装 LNMP环境
- FrameLayout measure过程源码Log全解析之二:修改framework代码,输出Log
- SQlServer 安装出错:未指定 INSTANCESHAREDWOWDIR 命令行值
- LUA面向对象程序设计(六)数据的封装
- 智能家居:智能中心还是消息总线(I)