面向对象编程 #
一、面向对象基础 #
1.1 Lua 中的对象 #
Lua 没有内置的类系统,但可以通过表和元表实现面向对象:
lua
-- 对象是表
local person = {
name = "Alice",
age = 30,
greet = function(self)
print("Hello, I'm " .. self.name)
end
}
person:greet() -- Hello, I'm Alice
1.2 冒号语法 #
lua
-- 冒号定义方法(自动添加 self 参数)
local person = {
name = "Alice",
age = 30
}
function person:greet()
print("Hello, I'm " .. self.name)
end
-- 等价于
function person.greet(self)
print("Hello, I'm " .. self.name)
end
-- 调用
person:greet() -- 冒号调用
person.greet(person) -- 点调用
二、实现类 #
2.1 基本类 #
lua
local Person = {}
Person.__index = Person
-- 构造函数
function Person:new(name, age)
local instance = setmetatable({}, self)
instance.name = name
instance.age = age
return instance
end
-- 方法
function Person:greet()
print(string.format("Hello, I'm %s, %d years old.", self.name, self.age))
end
function Person:get_age()
return self.age
end
-- 使用
local alice = Person:new("Alice", 30)
local bob = Person:new("Bob", 25)
alice:greet() -- Hello, I'm Alice, 30 years old.
bob:greet() -- Hello, I'm Bob, 25 years old.
2.2 带初始化方法的类 #
lua
local Person = {}
Person.__index = Person
function Person:new(name, age)
local instance = setmetatable({}, self)
instance:init(name, age)
return instance
end
function Person:init(name, age)
self.name = name
self.age = age
end
function Person:greet()
print("Hello, I'm " .. self.name)
end
2.3 类属性和方法 #
lua
local Counter = {}
Counter.__index = Counter
-- 类属性(静态属性)
Counter.count = 0
function Counter:new()
Counter.count = Counter.count + 1
return setmetatable({id = Counter.count}, self)
end
-- 实例方法
function Counter:get_id()
return self.id
end
-- 类方法(静态方法)
function Counter.get_total()
return Counter.count
end
local c1 = Counter:new()
local c2 = Counter:new()
print(c1:get_id()) -- 1
print(c2:get_id()) -- 2
print(Counter.get_total()) -- 2
三、继承 #
3.1 单继承 #
lua
-- 父类
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
local instance = setmetatable({}, self)
instance.name = name
return instance
end
function Animal:speak()
print(self.name .. " makes a sound")
end
-- 子类
local Dog = setmetatable({}, {__index = Animal})
Dog.__index = Dog
function Dog:new(name, breed)
local instance = Animal.new(self, name)
instance.breed = breed
return instance
end
function Dog:speak()
print(self.name .. " says: Woof!")
end
-- 子类
local Cat = setmetatable({}, {__index = Animal})
Cat.__index = Cat
function Cat:new(name, color)
local instance = Animal.new(self, name)
instance.color = color
return instance
end
function Cat:speak()
print(self.name .. " says: Meow!")
end
-- 使用
local dog = Dog:new("Buddy", "Golden Retriever")
local cat = Cat:new("Whiskers", "Orange")
dog:speak() -- Buddy says: Woof!
cat:speak() -- Whiskers says: Meow!
3.2 调用父类方法 #
lua
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
return setmetatable({name = name}, self)
end
function Animal:introduce()
print("I am an animal named " .. self.name)
end
local Dog = setmetatable({}, {__index = Animal})
Dog.__index = Dog
function Dog:new(name, breed)
local instance = Animal.new(self, name)
instance.breed = breed
return instance
end
function Dog:introduce()
-- 调用父类方法
Animal.introduce(self)
print("I am a " .. self.breed)
end
local dog = Dog:new("Buddy", "Golden Retriever")
dog:introduce()
-- I am an animal named Buddy
-- I am a Golden Retriever
3.3 多重继承 #
lua
local function create_class(...)
local parents = {...}
local class = {}
-- 查找方法
local function search(key, parents)
for _, parent in ipairs(parents) do
if parent[key] then
return parent[key]
end
end
end
setmetatable(class, {
__index = function(_, key)
return search(key, parents)
end
})
class.__index = class
function class:new(...)
local instance = setmetatable({}, self)
if instance.init then
instance:init(...)
end
return instance
end
return class
end
-- 使用
local A = {value_a = "A"}
function A:method_a()
print("Method A: " .. self.value_a)
end
local B = {value_b = "B"}
function B:method_b()
print("Method B: " .. self.value_b)
end
local C = create_class(A, B)
function C:init(x)
self.value_a = x
self.value_b = x
end
local c = C:new("X")
c:method_a() -- Method A: X
c:method_b() -- Method B: X
四、封装 #
4.1 私有成员 #
lua
local BankAccount = {}
BankAccount.__index = BankAccount
function BankAccount:new(initial_balance)
-- 私有变量
local balance = initial_balance or 0
local instance = setmetatable({}, self)
-- 公共方法访问私有变量
function instance:deposit(amount)
balance = balance + amount
end
function instance:withdraw(amount)
if amount <= balance then
balance = balance - amount
return true
end
return false
end
function instance:get_balance()
return balance
end
return instance
end
local account = BankAccount:new(100)
account:deposit(50)
print(account:get_balance()) -- 150
-- account.balance = 0 -- 无效,balance 是私有的
4.2 保护成员 #
lua
local Person = {}
Person.__index = Person
function Person:new(name, age)
local instance = setmetatable({}, self)
instance._name = name -- 保护成员(约定)
instance._age = age
return instance
end
function Person:get_name()
return self._name
end
function Person:get_age()
return self._age
end
function Person:set_age(age)
if age > 0 then
self._age = age
end
end
五、多态 #
5.1 方法重写 #
lua
local Shape = {}
Shape.__index = Shape
function Shape:new(name)
return setmetatable({name = name}, self)
end
function Shape:area()
return 0
end
function Shape:perimeter()
return 0
end
function Shape:describe()
print(string.format("%s: area=%.2f, perimeter=%.2f",
self.name, self:area(), self:perimeter()))
end
local Rectangle = setmetatable({}, {__index = Shape})
Rectangle.__index = Rectangle
function Rectangle:new(width, height)
local instance = Shape.new(self, "Rectangle")
instance.width = width
instance.height = height
return instance
end
function Rectangle:area()
return self.width * self.height
end
function Rectangle:perimeter()
return 2 * (self.width + self.height)
end
local Circle = setmetatable({}, {__index = Shape})
Circle.__index = Circle
function Circle:new(radius)
local instance = Shape.new(self, "Circle")
instance.radius = radius
return instance
end
function Circle:area()
return math.pi * self.radius ^ 2
end
function Circle:perimeter()
return 2 * math.pi * self.radius
end
-- 多态
local shapes = {
Rectangle:new(3, 4),
Circle:new(5),
Rectangle:new(2, 6)
}
for _, shape in ipairs(shapes) do
shape:describe()
end
-- Rectangle: area=12.00, perimeter=14.00
-- Circle: area=78.54, perimeter=31.42
-- Rectangle: area=12.00, perimeter=16.00
六、类工厂 #
6.1 通用类创建器 #
lua
local function class(parent)
local c = {}
c.__index = c
if parent then
setmetatable(c, {__index = parent})
end
function c:new(...)
local instance = setmetatable({}, self)
if instance.init then
instance:init(...)
end
return instance
end
function c:extend()
return class(self)
end
return c
end
-- 使用
local Animal = class()
function Animal:init(name)
self.name = name
end
function Animal:speak()
print(self.name .. " makes a sound")
end
local Dog = Animal:extend()
function Dog:init(name, breed)
Animal.init(self, name)
self.breed = breed
end
function Dog:speak()
print(self.name .. " says: Woof!")
end
local dog = Dog:new("Buddy", "Golden Retriever")
dog:speak() -- Buddy says: Woof!
七、接口与混入 #
7.1 混入模式 #
lua
-- 定义混入
local Printable = {
print_info = function(self)
print(tostring(self))
end
}
local Comparable = {
__eq = function(a, b)
return a:value() == b:value()
end,
__lt = function(a, b)
return a:value() < b:value()
end
}
-- 应用混入
local function mixin(class, ...)
for _, m in ipairs({...}) do
for k, v in pairs(m) do
class[k] = class[k] or v
end
end
end
local Item = {}
Item.__index = Item
function Item:new(value)
return setmetatable({value = value}, self)
end
function Item:value()
return self.value
end
function Item:__tostring()
return "Item(" .. self.value .. ")"
end
mixin(Item, Printable, Comparable)
local a = Item:new(10)
local b = Item:new(20)
a:print_info() -- Item(10)
print(a < b) -- true
八、总结 #
本章介绍了 Lua 面向对象编程:
- 对象基础:表和冒号语法
- 类实现:构造函数、方法
- 继承:单继承、多重继承
- 封装:私有成员、保护成员
- 多态:方法重写
- 类工厂:通用类创建器
- 混入模式:代码复用
下一章,我们将学习协程。
最后更新:2026-03-27