0Pricing
Lua Academy · 课时

基类和构造函数设计

设计 Class() 工厂,设置元表和 new() 构造函数。

基类和构造函数设计 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Lua Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Lua Academy 课程共包含 4 节课。

目标:可复用的类工厂

我们需要一个 Class() 函数,它能返回一个新的类对象,并正确实现构造函数、方法查找和面向对象语义。

类工厂骨架

工厂会创建一个类表,并为其设置用于方法分派的元表。

local function Class()
  local cls = {}
  cls.__index = cls
  cls.__name = "AnonymousClass"
  function cls:new(...)
    local instance = setmetatable({}, cls)
    if instance.init then instance:init(...) end
    return instance
  end
  return cls
end

定义类

创建一个类,定义 init(构造函数),并添加方法。

local Animal = Class()
Animal.__name = "Animal"
function Animal:init(name, sound)
  self.name = name
  self.sound = sound
end
function Animal:speak()
  print(self.name .. " says " .. self.sound)
end
local cat = Animal:new("Cat", "Meow")
cat:speak()  -- Cat says Meow

构造函数模式

构造函数 :new(...) 通过 setmetatable({}, cls) 创建实例,然后调用 :init(...) 完成初始化。这样可以将分配与初始化分离。

用于调试的类名

保存 cls.__name,并定义 __tostring,使实例能够打印出有意义的信息。

function Animal:__tostring()
  return "<" .. Animal.__name .. ": " .. self.name .. ">"
end
print(tostring(cat))  -- <Animal: Cat>

在 init 中设置默认值

使用 or 在 init 中提供默认值。

function Vehicle:init(opts)
  self.speed  = opts.speed  or 0
  self.fuel   = opts.fuel   or 100
  self.engine = opts.engine or "petrol"
end

类方法与实例方法

使用 function cls.method() 定义的方法是类方法(没有 self)。使用 function cls:method() 定义的方法会接收实例作为自身参数。

静态属性

直接设置在类表上的属性会由所有实例共享,除非被实例字段遮蔽。

Animal.count = 0
function Animal:init(name, sound)
  Animal.count = Animal.count + 1
  self.name = name; self.sound = sound
end
print(Animal.count)  -- 0
Animal:new("Dog","Woof")
print(Animal.count)  -- 1

复制构造函数

:clone() 方法通过浅复制实例字段来创建实例的副本。

function Animal:clone()
  local copy = setmetatable({}, getmetatable(self))
  for k, v in pairs(self) do copy[k] = v end
  return copy
end

相等元方法

定义 __eq,以便对实例进行有意义的相等比较。

Animal.__eq = function(a, b)
  return a.name == b.name
end

为什么不用 rawget

请使用 self.field 而不是 rawget,以便派生类支持基于元方法的字段访问。只有在明确需要绕过这种机制时,才使用 rawget。

构造函数设计问题

为什么要将 init 与 new 分配器分开调用?

回顾:基类与构造函数

Class() 工厂将一个表创建为类,设置 __index = cls 以进行方法查找,并提供 :new() 和 :init()。这是所有 Lua 面向对象编程模式的基础。

常见问题解答

「基类和构造函数设计」课时是免费的吗?

是的 — 「基类和构造函数设计」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。

「基类和构造函数设计」这节课中我会学到什么?

设计 Class() 工厂,设置元表和 new() 构造函数。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Lua Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「基类和构造函数设计」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Lua Academy 课中编写并运行代码吗?

能。每节 Lua Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 基类和构造函数设计
  2. 多级继承
  3. 混入组合和接口检查
  4. instanceof 和类型自省
← 返回 Lua Academy