先来了解一下多态的概念。在面向对象语言中,多态本质就是运行时绑定,比如有一个父类BaseClass,它有2个子类subClass1,subClass2。BaseClass有一个方法func(),两个子类都重写了这个方法。那么我们可以定义一个BaseClass的引用obj,让它指向一个子类的对象,比如BaseClass obj = new subClass1();那么我们调用obj.func()方法时候,会进行动态绑定,也就是obj它的实际类型的func()方法,即subClass1的func()方法。同样BaseClass obj = new subClass2();obj.func()其实调用的是subClass2的func()方法。这种由于子类重写父类方法,然后用父类引用指向子类对象,调用方法时候会进行动态绑定,这就是多态。
但是,在Lua中没有类型的概念,不存在像c++中那样用基类的引用或指针来指向派生类,因此,在Lua中模拟的多态只能说是:基类生成的对象会调用基类的方法,如果它的子类重写了该方法,那么子类生成的对象就会调用子类的这个方法,而不会去调用基类中的方法。
我们还是以《LUA面向对象程序设计(二)继承》中的例子来进行说明:
local Vehicle = {
wheels = 4,
speed = 100,
color = "b"
}
Vehicle.__index = Vehicle
function Vehicle:New(wheels, speed, color)
local obj = {}
setmetatable(obj, self)
obj.wheels = wheels
obj.speed = speed
obj.color = color
return obj
end
function Vehicle:getSpeed()
print(self.speed)
end
function Vehicle:setSpeed(x)
self.speed = x
end
--新增了新的函数接口
function Vehicle:getPluss()
return 50
end
function Vehicle:speedPluss()
--在这里调用getPluss接口,如果是基类对象,就调用基类的方法,如果是子类实例,就调用子类的方法
self.speed = self:getPluss()+ 1
end
local Bicycle = { engine = 1 }
setmetatable(Bicycle, Vehicle)--这里就实现了Bicycle对Vehicle的继承
Bicycle.__index = Bicycle --这样就实现了一个类,以便Bicycle的每个实例都到Bicycle进行查找
function Bicycle:New(engine)
local obj = {}
obj = Vehicle:New(2, 10, "r")
obj.engine = engine --除了继承基类成员外,添加自己成员
setmetatable(obj, self) --使得Bicycle的每个实例都与Bicycle挂钩
return obj
end
function Bicycle:setSpeed(s)
self.speed = s
end
function Bicycle:getSpeed()
print(self.speed)
end
--在这里重定义了基类的getPluss
function Bicycle:getPluss()
return 10
end
function Bicycle:printAll()
print(self.speed .. "," .. self.wheels ..",".. self.color .. "," .. self.engine)
end
--分别定义一个基类对象和子类对象
b = Vehicle:New() --use default value
s = Bicycle:New(3)
b:getSpeed()
s:getSpeed()
b:speedPluss()
s:speedPluss()
b:getSpeed()
s:getSpeed()
输出结果:
100
10
51
11
从中我们可以看到,在调用speedPluss方法时,基类对象b和子类对象s分别调用了自己的方法getPluss,基类的方法返回的结果是50,因此最终结果是51,子类方法返回的是10,因此最终的结果是11。这就是Lua中的多态性。
(全文完)