实例变量
本课属于 Coddy Lua 学习旅程的“面向对象编程”单元。第 12 课,共 70 课。
欢迎来到新的一章,本章将介绍对象如何管理其内部数据。你已经学会了创建类和实例,现在该探索每个实例如何存储和管理自己的独特状态了。
实例变量是只属于单个对象的字段。当你在方法或构造函数中给 self.something 赋值时,这些数据只存在于那个特定实例中。同一类的其他对象都有各自独立的副本。
存储表格等复杂数据时,这一点尤其重要。考虑一个库存系统,其中每个角色都携带不同的物品:
local Inventory = {}
Inventory.__index = Inventory
function Inventory:new()
local instance = {}
setmetatable(instance, self)
instance.items = {} -- 每个实例都有自己的空表
return instance
end
function Inventory:addItem(item)
table.insert(self.items, item)
end关键行是 instance.items = {}。在构造函数中创建一个新的空表后,每个库存对象都会拥有自己的独立列表。如果你改为在类表本身中定义 items,所有实例就会意外地共用同一个表:给一个角色添加一把剑,就会让所有角色都得到这把剑!
local bag1 = Inventory:new()
local bag2 = Inventory:new()
bag1:addItem("Sword")
bag2:addItem("Potion")
print(#bag1.items) -- 输出:1
print(#bag2.items) -- 输出:1每个库存都维护自己的集合。当某个实例需要跟踪独立变化的数据时,都可以使用这种模式:列表、计数器,或该对象独有的任何可变状态。
挑战
简单我们来构建一个 ShoppingCart 系统,让每个购物车都维护自己的商品列表。这将演示实例变量如何让不同对象的数据彼此隔离:向一个购物车添加商品不会影响另一个购物车!
你将把代码分成两个文件:
ShoppingCart.lua:定义ShoppingCart类,让每个实例都有自己的products表。需要包含::new()构造函数,为每个购物车初始化一个空商品列表:addProduct(productName)方法,将商品添加到这个购物车的列表中:listProducts()方法,每行打印一个商品
main.lua:引入 ShoppingCart 模块,并创建两个独立的购物车。向每个购物车添加不同的商品,以证明它们拥有彼此独立的商品库存。
你将收到 4 个输入:
- 要添加到购物车 A 的第一个商品
- 要添加到购物车 A 的第二个商品
- 要添加到购物车 B 的第一个商品
- 要添加到购物车 B 的第二个商品
在主文件中:
- 创建两个购物车:
cartA和cartB - 将前两个商品添加到
cartA - 将后两个商品添加到
cartB - 打印
Cart A:,然后列出购物车 A 中的商品 - 打印
Cart B:,然后列出购物车 B 中的商品
例如,如果输入是 Apple、Bread、Milk 和 Eggs,输出应为:
Cart A:
Apple
Bread
Cart B:
Milk
Eggs请记住:关键是在构造函数中将 products 初始化为一个新的空表。这样,每个购物车实例都会拥有自己的独立列表,而不是所有购物车共用同一个表。
亲手试试
-- 加载 ShoppingCart 模块
local ShoppingCart = require('ShoppingCart')
-- 读取输入
local product1 = io.read()
local product2 = io.read()
local product3 = io.read()
local product4 = io.read()
-- TODO: 创建两个购物车:cartA 和 cartB
-- TODO: 将 product1 和 product2 添加到 cartA
-- TODO: 将 product3 和 product4 添加到 cartB
-- TODO: 打印 "Cart A:",然后列出 cartA 中的商品
-- TODO: 打印 "Cart B:",然后列出 cartB 中的商品
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Lua 在线编译器