字符串格式化
本课属于 Coddy Lua 学习旅程的“面向对象编程”单元。第 16 课,共 70 课。
直接打印对象时,Lua 会显示类似 table: 0x55a... 这样没有帮助的信息。这只是一个内存地址。__tostring 元方法可以让你定义打印对象或将对象转换为文本时所显示的字符串。
在类模式中,你可以将 __tostring 添加为类表中的一个函数。由于类本身充当实例的元表,Lua 会自动找到并使用这个函数:
local Player = {}
Player.__index = Player
function Player:new(name, level)
local instance = {}
setmetatable(instance, self)
instance.name = name
instance.level = level
return instance
end
function Player:__tostring()
return "Player: " .. self.name .. " (Level " .. self.level .. ")"
end现在打印一个 Player 实例时,Lua 会自动调用你的 __tostring 方法:
local hero = Player:new("Luna", 5)
print(hero) -- 输出:Player: Luna (Level 5)注意,__tostring 使用冒号语法并接收 self,这样你就可以访问所有实例数据。函数必须返回一个字符串。你可以根据对象的实际情况来设置格式,将各个属性组合成易读的表示形式。
挑战
简单让我们来创建一个懂得如何介绍自己的 Book 类吧!直接打印一本书时,Lua 会显示格式清晰的字符串,而不是难以理解的内存地址,这都要归功于 __tostring 元方法。
你需要将代码分别放在两个文件中:
Book.lua:使用标准的原型模式定义Book类。每本书都应保存一个title和一个author。添加一个:new(title, author)构造函数,并实现__tostring元方法,让打印书籍时以易读的格式显示书籍信息。main.lua:引入 Book 模块,创建书籍实例,并直接打印它们,查看自定义字符串格式的效果。
你的 __tostring 方法应返回以下格式的字符串:
"[title]" by [author]注意,输出字符串中的书名用双引号括起来。
你会收到 4 个输入:
- 第一本书的书名
- 第一本书的作者
- 第二本书的书名
- 第二本书的作者
在主文件中,使用给定的输入创建两本书,并直接打印每本书(不要调用方法,只需使用 print(book))。每本书都应单独占一行。
例如,如果输入是 The Hobbit、J.R.R. Tolkien、1984 和 George Orwell,输出应为:
"The Hobbit" by J.R.R. Tolkien
"1984" by George Orwell请记住,__tostring 必须返回一个字符串。由于你的类表充当实例的元表,打印书籍时,Lua 会自动查找并使用你的 __tostring 函数。
亲手试试
-- 加载 Book 模块
local Book = require('Book')
-- 读取输入
local title1 = io.read()
local author1 = io.read()
local title2 = io.read()
local author2 = io.read()
-- TODO:使用 Book:new() 创建两个书籍实例
-- TODO:直接打印每本书(只需使用 print(book))
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Lua 在线编译器