Lua - Metatables: A Beginner's Guide

Здравствуйте,野心勃勃的程序设计师们!今天,我们将踏上一段激动人心的旅程,探索Lua元表的世界。如果你以前从未编写过一行代码,也不用担心——我将是你友好的向导,我们将一起探索这个迷人的主题。那么,拿起你最喜欢的饮料,让我们一起深入探讨吧!

Lua - Metatables

什么是元表?

在我们深入了解细节之前,让我们先了解一下元表是什么。想象你有一个神奇的工具箱,可以赋予普通的Lua表超能力。这就是元表的作用!它是一个普通的Lua表,为另一个表定义特殊行为。

__index 元方法

我们这次神奇旅程的第一站是 __index 元方法。这个小巫师帮助我们来处理表中缺失的键。

__index 的基本用法

让我们从一个简单的例子开始:

local fruits = {apple = "red", banana = "yellow"}
local metatable = {
__index = function(table, key)
return "unknown color"
end
}
setmetatable(fruits, metatable)

print(fruits.apple)    -- Вывод: red
print(fruits.cherry)   -- Вывод: unknown color

在这个例子中,我们创建了一个 fruits 表和一个带有 __index 函数的元表。当我们尝试访问一个不存在的键(比如 "cherry"),而不是给我们一个错误,Lua 调用我们的 __index 函数,返回 "unknown color"。

__index 作为表

__index 元方法也可以是一个表:

local animals = {dog = "woof", cat = "meow"}
local metatable = {
__index = {
cow = "moo",
pig = "oink"
}
}
setmetatable(animals, metatable)

print(animals.dog)  -- Вывод: woof
print(animals.cow)  -- Вывод: moo

在这里,如果 animals 中没有找到键,Lua 会查看 __index 表来寻找。

__newindex 元方法

接下来是 __newindex,新键赋值的大门守卫。

local protected = {}
local metatable = {
__newindex = function(table, key, value)
error("This table is read-only!")
end
}
setmetatable(protected, metatable)

protected.newKey = "test"  -- Это вызовет ошибку

在这个例子中,任何尝试向 protected 添加新键的行为都会触发我们的错误消息。就像给你的表请了一个保安!

给表添加操作符行为

现在,让我们给我们的表一些数学技能!

__add 元方法

local vector = {x = 10, y = 20}
local metatable = {
__add = function(v1, v2)
return {x = v1.x + v2.x, y = v1.y + v2.y}
end
}
setmetatable(vector, metatable)

local result = vector + {x = 5, y = 10}
print(result.x, result.y)  -- Вывод: 15 30

我们刚刚教会了我们的 vector 表如何进行加法!__add 元方法在我们对表使用 + 操作符时被调用。

__call 元方法

想让你的表表现得像函数一样吗?来见见 __call

local greeter = {name = "Lua Lover"}
local metatable = {
__call = function(table, greeting)
return greeting .. ", " .. table.name .. "!"
end
}
setmetatable(greeter, metatable)

print(greeter("Hello"))  -- Вывод: Hello, Lua Lover!

现在我们的 greeter 表可以像函数一样被调用。神奇,对吧?

__tostring 元方法

最后但同样重要的是,让我们用 __tostring 使我们的表更具表现力。

local person = {name = "Alice", age = 30}
local metatable = {
__tostring = function(table)
return table.name .. " is " .. table.age .. " years old"
end
}
setmetatable(person, metatable)

print(person)  -- Вывод: Alice is 30 years old

__tostring 元方法在我们尝试将表转换为字符串时被调用,比如当我们使用 print() 时。

结论

恭喜你!你已经迈出了进入Lua元表美妙世界的第一步。我们涵盖了很多内容,从用 __index 处理缺失键到用 __call 使我们的表可调用。记住,熟能生巧,所以不要害怕用这些概念进行实验。

以下是我们在本次学习中了解到的元方法快速参考表:

元方法 目的
__index 处理访问缺失键
__newindex 控制新键的添加
__add 定义加法行为
__call 使表可调用
__tostring 提供表的字符串表示

继续探索,继续编码,最重要的是,用Lua享受乐趣!谁知道你会创造出什么神奇的程序呢?

Credits: Image by storyset