Menu
CoddyTech

添加子类方法

本课属于 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 中不存在这个方法。这就是继承如何让你在保留共享功能的同时实现行为的专门化。

challenge icon

挑战

简单

让我们构建一个宠物类层次结构,让猫拥有自己的特殊能力!你将创建一个 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() 方法
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Lua 在线编译器