Menu
CoddyTech

委托

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

将一个对象存储在另一个对象中只是第一步。组合真正的强大之处在于委托,也就是外部对象将方法调用转发给其内部组件。

想一想启动汽车的过程。你不会伸到引擎盖下面手动转动发动机,而是转动钥匙,汽车会在内部完成剩下的工作。

在代码中,这意味着 Car 类提供了一个简单的 :start() 方法,并将实际工作委托给引擎:

function Car:start()
    print("Turning the key...")
    self.engine:run()  -- 交给内部对象处理
end

汽车不需要知道发动机是如何运行的。它只需告诉发动机做好自己的工作。这样可以分离各自的职责。Engine 类负责处理发动机逻辑,而 Car 负责协调各个部分:

function Engine:run()
    print("Engine running at " .. self.horsepower .. " HP")
end

local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- 输出:
-- 正在转动钥匙……
-- Engine 正以 250 HP 运行

委托为类的使用者提供了清晰的接口。他们与汽车交互,而不是与汽车的内部部件交互。如果你之后换用不同的引擎实现,汽车的公共接口仍然保持不变:只有内部的委托会改变。

challenge icon

挑战

简单

让我们构建一个展示委托的音乐播放器系统!你将创建一个 Speaker 组件,以及一个包含它的 MusicPlayer。播放器不会直接处理声音输出,而是把这项工作委托给内部的扬声器。

你将把代码分别写在三个文件中:

  • Speaker.lua:创建一个 Speaker 类,其构造函数 :new(volume) 用于保存音量。添加一个 :playSound(trackName) 方法,用于打印:Playing "{trackName}" at volume {volume}
  • MusicPlayer.lua:创建一个 MusicPlayer 类,其构造函数 :new(brand, speaker) 接收品牌名称和一个 Speaker 对象。播放器会将扬声器保存在自身内部。添加以下方法:
    • :play(trackName):打印 {brand} player starting...,然后将工作委托给扬声器的 :playSound() 方法
    • :stop():打印 {brand} player stopped
  • main.lua:把所有部分组合起来!读取扬声器音量、播放器品牌和曲目名称。先创建一个 Speaker,再将它传给 MusicPlayer 构造函数。调用播放器的 :play() 方法并传入曲目名称,然后调用 :stop()。

你会收到 3 个输入:

  1. 扬声器音量(一个数字)
  2. 音乐播放器品牌(一个字符串)
  3. 要播放的曲目名称(一个字符串)

输出应显示播放器如何与扬声器协作:

{brand} player starting...
Playing "{trackName}" at volume {volume}
{brand} player stopped

例如,如果输入是 75、SoundMax 和 Summer Vibes,输出应为:

SoundMax player starting...
Playing "Summer Vibes" at volume 75
SoundMax player stopped

注意,MusicPlayer 并不知道如何发出声音。它只是让扬声器处理这部分工作。这就是委托的实际应用:外部对象提供简洁的接口,内部组件则负责专门的工作!

亲手试试

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

local Speaker = require('Speaker')
local MusicPlayer = require('MusicPlayer')

-- 读取输入
local volume = tonumber(io.read())
local brand = io.read()
local trackName = io.read()

-- TODO:用给定的音量创建一个 Speaker

-- TODO:用品牌和扬声器创建一个 MusicPlayer

-- TODO:用曲目名称调用播放器的 play 方法

-- TODO:调用播放器的 stop 方法
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Lua 在线编译器