Menu
CoddyTech

方法重写

本课属于 Coddy Lua 学习旅程的“面向对象编程”单元。第 37 课,共 70 课。

到目前为止,子类继承了父类的方法,并添加了新方法。但如果子类需要使用相同的方法名,却实现不同的行为,该怎么办?这叫作方法重写。

当你在子类中定义一个与父类同名的方法时,会优先使用子类中的版本。Lua 的查找链会先检查子类,如果在那里找到该方法,就会停止查找。

local Animal = {}
Animal.__index = Animal

function Animal:new(name)
    local obj = {name = name}
    setmetatable(obj, Animal)
    return obj
end

function Animal:speak()
    print(self.name .. " makes a sound")
end

-- Dog 重写了 speak() 方法
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

function Dog:speak()
    print(self.name .. " barks: Woof!")
end

现在,每个类对同一个方法调用的响应都不同:

local generic = Animal:new("Creature")
local buddy = Dog:new("Buddy")

generic:speak()  -- 输出:Creature makes a sound
buddy:speak()    -- 输出:Buddy barks: Woof!

Dog 的 :speak() 会完全替换父类中的版本,并应用于 Dog 实例。这样,你就可以在保持接口一致的同时创建专门的行为:每种动物都可以 :speak(),但每个物种的实现方式各不相同。

challenge icon

挑战

简单

让我们构建一个小小的动物王国,让不同的动物用各自独特的方式说话!你将创建一个 Animal 父类,以及两个子类 Cat 和 Cow。它们都会重写父类的 :speak() 方法,实现各自的专属行为。

你需要把代码分成 4 个文件:

  • Animal.lua:基类,包含一个 :new(name) 构造函数,用于保存动物的名字。还要添加一个 :speak() 方法,打印动物的名字,后面跟着 makes a sound。这是子类将要重写的默认行为。
  • Cat.lua:一个继承自 Animal 的子类。它的 :new(name) 构造函数应调用父类构造函数,然后重新将元表关联到 Cat。重写 :speak() 方法,让猫发出不同的声音:打印猫的名字,后面跟着 meows: Meow!
  • Cow.lua:另一个继承自 Animal 的子类。构造函数的设置方式与 Cat 相同。重写 :speak() 方法,让奶牛打印自己的名字,后面跟着 moos: Moo!
  • main.lua:把所有内容整合起来!从输入中读取两个名字,用第一个名字创建一个 Cat,用第二个名字创建一个 Cow,然后分别对它们调用 :speak(),演示同一个方法名如何根据类的不同产生不同的输出。

你会收到两个输入:

  1. 猫的名字
  2. 奶牛的名字

在主文件中,创建这两只动物,并先对猫调用 :speak(),再对奶牛调用。

例如,如果输入是 Whiskers 和 Bessie,输出应为:

Whiskers meows: Meow!
Bessie moos: Moo!

注意,两只动物都会响应同一个 :speak() 方法调用,但各自的输出会根据其类型而不同。Cat 的版本完全替代了父类通用的“makes a sound”行为,Cow 的版本也是如此。这就是方法重写:接口相同,实现不同!

亲手试试

-- main.lua:把所有部分组合起来

local Cat = require('Cat')
local Cow = require('Cow')

-- 读取输入
local catName = io.read()
local cowName = io.read()

-- TODO:用第一个名字创建一个 Cat 对象

-- TODO:用第二个名字创建一个 Cow 对象

-- TODO:先对猫调用 :speak(),再对牛调用 :speak()
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Lua 在线编译器