基于表的对象系统
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: 4005. 总结
尽管 Lua 没有内建的类和继承机制,但表和元表的组合就能实现类的定义、实例的创建、继承和组合。全篇用到的原语只有 setmetatable 和 __index,其余都是约定。