添加子类方法
本课属于 Coddy Lua 学习旅程的“面向对象编程”单元。第 34 课,共 70 课。
继承让子类可以访问父类的方法,但它真正的强大之处在于添加只有子类才有的新方法。Dog 可以做 Animal 能做的一切,还能做狗特有的事情,比如吠叫。
添加子类专属的方法很简单:只需在子类表中定义它。由于实例会先在自己的类中查找方法,因此它们能找到这个新方法,而且不会影响父类。
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
local obj = {name = name}
setmetatable(obj, Animal)
return obj
end
function Animal:breathe()
print(self.name .. " is breathing")
end
-- Dog 继承自 Animal
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new(name)
local obj = Animal.new(Animal, name)
setmetatable(obj, Dog)
return obj
end
-- Dog 独有的新方法
function Dog:bark()
print(self.name .. " says: Woof!")
end现在,Dog 实例既可以使用继承的方法,也可以使用独有的方法:
local buddy = Dog:new("Buddy")
buddy:breathe() -- 输出:Buddy is breathing(继承而来)
buddy:bark() -- 输出:Buddy says: Woof!(仅子类有)父类保持不变:对普通的 Animal 调用 :bark() 会失败,因为 Animal 中不存在这个方法。这就是继承如何让你在保留共享功能的同时实现行为的专门化。
挑战
简单让我们构建一个宠物类层次结构,让猫拥有自己的特殊能力!你将创建一个 Pet 父类和一个 Cat 子类。Cat 会继承 Pet 的所有内容,同时还拥有一个只有猫才能使用的独特方法。
你将把代码分到三个文件中:
Pet.lua:定义父类,并添加一个:new(name)构造函数来保存宠物的名字。添加一个:greet()方法,打印宠物的名字,后面接上says hello。设置标准的类结构,并返回这个类。Cat.lua:定义继承自 Pet 的子类。Cat 的:new(name)构造函数应调用父类构造函数来初始化名字,然后将元表重新关联到 Cat。添加一个仅属于子类的:purr()方法,打印猫的名字,后面接上purrs contentedly。这个方法只存在于 Cat 中,Pet 没有这个方法!main.lua:引入 Cat 模块,从输入中读取一个名字,创建一个 Cat 实例,并展示它既能使用继承来的:greet()方法,也能使用自己的独特:purr()方法。
你会收到一个输入:猫的名字。
在主文件中,用给定的名字创建一个 Cat,然后在不同的行上依次调用 :greet() 和 :purr()。
例如,如果输入是 Whiskers,输出应为:
Whiskers says hello
Whiskers purrs contentedly第一行来自 Pet 中定义的继承方法 :greet(),第二行来自只存在于 Cat 中的 :purr() 方法。这展示了子类如何做到父类能做的一切,还能拥有自己的专属行为!
亲手试试
-- main.lua:创建 Cat 实例并演示继承
local Cat = require('Cat')
-- 从输入中读取猫的名字
local name = io.read()
-- TODO:用给定的名字创建 Cat 实例
-- TODO:调用从 Pet 继承的 :greet() 方法
-- TODO:调用 Cat 特有的 :purr() 方法
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Lua 在线编译器