Skip to content

基于表的对象系统 ​

Lua 本身并没有内建的类和继承机制,但利用表(tables)和元表(metatables),可以搭出类、实例、继承这些面向对象的特性。

1. 基本概念 ​

表是 Lua 的核心数据结构,数组、字典、对象都能用它表示,对象系统就建在表上。元表给表附加行为,比如操作符重载,或者在访问不存在的字段时执行特定操作。

2. 定义类和创建实例 ​

通过表和元表,可以模拟类和实例的概念。以下是一个简单的实现:

2.1 定义类 ​

定义一个类通常涉及创建一个表并为其指定一个元表。这个元表会包含类的方法。

lua
local Dog = {}
Dog.__index = Dog

function Dog:new(name, age)
    local instance = setmetatable({}, self)
    instance.name = name
    instance.age = age
    return instance
end

function Dog:bark()
    print(self.name .. " says: Woof!")
end

在这个例子中:

  • Dog 表代表一个类。
  • Dog.__index = Dog 使得 Dog 表的实例可以访问 Dog 表中定义的方法。
  • Dog:new 是一个构造函数,用来创建新的 Dog 实例。
  • Dog:bark 是一个实例方法,所有 Dog 实例都可以调用它。

2.2 创建实例 ​

创建实例是通过调用 new 方法完成的:

lua
local myDog = Dog:new("Rex", 5)
myDog:bark()  -- 输出 Rex says: Woof!

3. 继承 ​

Lua 支持基于原型的继承:创建一个新的表,把它作为已有表的扩展。

3.1 定义继承 ​

下面的示例在 Dog 类的基础上创建一个 Poodle 类,并加上它特有的行为:

lua
local Poodle = setmetatable({}, { __index = Dog })
Poodle.__index = Poodle

function Poodle:new(name, age, size)
    local instance = Dog:new(name, age)
    setmetatable(instance, self)
    instance.size = size
    return instance
end

function Poodle:describe()
    print(self.name .. " is a " .. self.size .. " poodle.")
end

在这个例子中:

  • Poodle 表通过 setmetatable 继承了 Dog 表的方法和属性。
  • Poodle:new 方法调用了 Dog:new 方法来创建基本的 Dog 实例,并添加了 size 属性。
  • Poodle:describe 是 Poodle 类特有的方法,用来描述狗的大小。

3.2 使用继承 ​

创建 Poodle 实例并使用其特有的方法:

lua
local myPoodle = Poodle:new("Fluffy", 3, "large")
myPoodle:bark()      -- 输出 Fluffy says: Woof!
myPoodle:describe()  -- 输出 Fluffy is a large poodle.

4. 组合 ​

除了继承,Lua 中的对象系统还可以通过组合来实现复用。组合指的是将一个对象作为另一个对象的属性来实现功能的扩展。

4.1 组合示例 ​

lua
local Engine = {}
Engine.__index = Engine

function Engine:new(type, horsepower)
    local instance = setmetatable({}, self)
    instance.type = type
    instance.horsepower = horsepower
    return instance
end

function Engine:info()
    print("Engine type: " .. self.type .. ", Horsepower: " .. self.horsepower)
end

local Car = {}
Car.__index = Car

function Car:new(make, model, engine)
    local instance = setmetatable({}, self)
    instance.make = make
    instance.model = model
    instance.engine = engine
    return instance
end

function Car:describe()
    print("Car make: " .. self.make .. ", model: " .. self.model)
    self.engine:info()
end

在这个例子中:

  • Engine 表示一个引擎类。
  • Car 表示一个汽车类,包含一个 Engine 实例作为属性。
  • Car:describe 方法调用 Engine:info 方法,展示了组合的实现。

4.2 使用组合 ​

lua
local myEngine = Engine:new("V8", 400)
local myCar = Car:new("Ford", "Mustang", myEngine)
myCar:describe()
-- 输出:
-- Car make: Ford, model: Mustang
-- Engine type: V8, Horsepower: 400

5. 总结 ​

尽管 Lua 没有内建的类和继承机制,但表和元表的组合就能实现类的定义、实例的创建、继承和组合。全篇用到的原语只有 setmetatable 和 __index,其余都是约定。

Hello Lua