继承方法
本课属于 Coddy Lua 学习旅程的“面向对象编程”单元。第 32 课,共 70 课。
建立继承关系后,子类实例会自动获得对所有父类方法的访问权限。这是通过 Lua 的查找链实现的:你在实例上调用方法时,Lua 会依次搜索各个关联的表,直到找到你要查找的内容。
考虑这样一种设置,其中 Animal 定义了一个 :breathe() 方法:
local Animal = {}
Animal.__index = Animal
function Animal:new()
local obj = {}
setmetatable(obj, Animal)
return obj
end
function Animal:breathe()
print("Breathing...")
end
-- Dog 继承自 Animal
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new()
local obj = {}
setmetatable(obj, Dog)
return obj
end现在看看创建一个 Dog 并调用父类方法时会发生什么:
local buddy = Dog:new()
buddy:breathe() -- 输出:Breathing...Dog 类从未定义 :breathe(),但它仍然可以正常工作。Lua 会先检查 buddy,没有找到,然后检查 Dog,仍然没有找到,最后在 Animal 中找到了它。这种自动继承方法的机制意味着,你只需在父类中编写一次共享行为,所有子类就能立即受益。
挑战
简单让我们构建一个简单的动物层次结构,看看方法继承如何发挥作用!你将创建一个 Animal 父类和一个 Dog 子类,然后演示 Dog 实例可以使用只在 Animal 中定义的方法。
你将把代码分成 3 个文件:
Animal.lua:使用标准的类模式定义父类。添加一个:new(name)构造函数,用来保存动物的名字;再添加一个:speak()方法,输出动物的名字,后面跟着makes a sound。在文件末尾返回这个类。Dog.lua:定义继承自 Animal 的子类。引入 Animal 模块,并设置继承关系,让 Dog 可以访问 Animal 的方法。添加一个:new(name)构造函数,用来保存名字并将 Dog 设置为元表。Dog 类不应该定义自己的:speak()方法,而是继承 Animal 中的这个方法。main.lua:引入 Dog 模块,从输入中读取一个名字,用这个名字创建一个 Dog 实例,并对它调用:speak()方法。
你将收到一个输入:狗的名字。
例如,如果输入是 Buddy,输出应该是:
Buddy makes a sound这里的关键是,Dog 类从未定义 :speak(),但对 Dog 实例调用它却能正常工作。Lua 会沿着查找链,从 Dog 实例到 Dog 类,再到找到该方法的 Animal 类。这就是继承的作用!
亲手试试
-- main.lua:入口文件
local Dog = require('Dog')
-- 从输入中读取狗的名字
local name = io.read()
-- TODO:用给定的名字创建一个 Dog 实例
-- TODO:调用 Dog 实例的 :speak() 方法
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Lua 在线编译器