LUA中的OOP(2) --- 单继承

其实单继承是前几天看的了,但是因为比较忙再加上今天下午摆弄了半天C#,所以一直没有总结。

前面说过lua本身只是一个脚本语言,在它上面玩OOP其实需要深入语言,利用语言提供的机制来实现OOP的机制。这次来看看针对OOP中单继承机制的一个实现方案,这个是根据《lua中文手册》上单继承那部分文章演化而来,我觉得书上的办法虽然看着很灵活但是却不够严格,或者说在语义上不够严谨,所以我做了一些改进,这个方案中我尽量靠近高级语言描述OOP时的文法,大家看完可以体会体会。

结合LUA自身的特点,在这个方案中,我定义了3个函数作为对OO本身描述的原语,分别是: CreateObject用于从指定的原型对象中生成一个新的对象实例;Inherit用于让子原型对象继承指定的父原型对象;Inheritable用于声明某个原型对象是可被继承的。单继承的实现就依靠在定义 原型对象时使用这些原语来达到目的。

<-------------Code Begin------------->


--[[

下面我们先来看3个原语的实现
]]-
-- 传递原型对象和待创建对象,返回新创建的对应类型的对象
function CreateObject(proto_type, newobj)
newobj = newobj or {};
setmetatable(newobj, proto_type);
return newobj;
end

--让child原型对象继承base原型对象
function Inherit(child, base)
setmetatable(child, base)
end

--使得一个原型对象具备"可被继承性"
function Inheritable(proto_type)
proto_type.__index = proto_type


--为proto_type的metatable添加写保护,只允许读取metatable而不许设置,保证继承链不被破坏
proto_type.__metatable = proto_type
end


--首先定义human类的原型
do

local function __print_age(self)
print(string.format("human age = %d", self.age))
end


local function __set_age(self, value)
self.age = value;
end


local function __get_age(self)
return self.agel;
end


human = {
age = 0,
set_age = __set_age,
print_age = __print_age,
get_age = __get_age,
};
--在这里用Inheritable原语声明human原型对象是可以被继承的
Inheritable(human)

end



--然后定义继承者Woman类的原型
do


local function __print_age(self)
print(string.format("woman age = %d", self.age))
end


woman = {
print_age = __print_age,
};
--在这里用Inheritable声明woman原型对象是可以被继承的,在我们这个例子中是否使用这个原语对能否继承其他原型对象并无

--影响。
Inheritable(woman);

--这一步是关键,使用Inherit原语,声明woman原型对象将会继承human原型对象,只要human原型对象使用过

--过Inheritable原语声明自己是可被继承的,那么这里只要用Inherit()原语即可完成继承。
Inherit(woman, human);

end

-- 最后我们来看测试代码,用CreateObject()原语为woman原型对象创建两个新实例对象
newobj0 = CreateObject(woman, {age = 25});
newobj1 = CreateObject(woman, {age = 24});


-- 运行下面的代码可以看到, newobj0和newobj1的属性相互不冲突,是两个完全独立的对象,同时也都继承了

--父类human的方法和属性,特别的,如果各位在上面woman类的定义里注释掉 print_age = __print_age 这句,

--就会发现这个继承本身就带有了一定虚函数的性质(这么说其实尚不严格),允许子类重新实现父类中的成员方法。
newobj1:print_age();
newobj0:print_age();

newobj0:set_age(15);

newobj1:print_age();
newobj0:print_age();

<-------------Code End------------->


原理:很简单,还是靠metatable。Inheritable和Inherit原语都是针对原型对象的metatable在做手脚。Inheritable原语会为原型对象增加__index成员并令

其指向自身,Inherit原语会让子原型对象的metatable指向父类,联合这两点就能看出,当在子类中查找某个不存在成员时会自动去

其父类中查找(因为设置了metatable指向父类,而父类的__index指向其自身)。更进一步的使用递归归纳法可以证得这2个继承原语的组合对任意深度的单继承均有效。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值