You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

类与实例的区别是什么?Lua中类与实例的代码差异问询

嘿,我来帮你把类和实例的区别讲透,尤其是Lua代码层面的具体差异,结合你给的示例来拆解~

类(Class)与实例(Instance)的通用区别

简单来说,二者的核心差异就是模板和实体的关系:

  • 类是一套通用蓝图:定义了某类对象共有的属性(比如位置、大小)和行为(比如更新、绘制),它本身只是个“规则集合”,不存储具体数据,也不占用内存来保存实例的状态。
  • 实例是具体的实体:根据类的蓝图创建出来的单个对象,每个实例都拥有类定义的属性和行为,但属性值是独属于自己的——就像“汽车”是类,你家那辆蓝色SUV就是实例,每辆车的颜色、里程都是各自独立的。
Lua中类与实例的代码层面差异

Lua本身没有原生的class语法,我们通常用表(table)+**元表(metatable)**来模拟类系统,你示例里用到的class库(比如很流行的middleclass)就是封装了这套底层逻辑的工具。下面结合你的代码来具体拆解:

1. 类的定义(你的class.widget.lua)

你代码里的widget就是一个类,本质是一个特殊的表,用来存储所有实例共享的方法和类级别的属性:

local class = require "class"
-- 创建类:这里的widget就是类对象,是一个存储了类规则的表
local widget = class("class.widget")

-- 用冒号(:)定义的是实例方法,自动传入self(后续调用时self会指向实例)
function widget:create()
    -- 这里定义的是实例属性的模板,每个实例创建后都会有自己的这些属性
    self.x = 0
    self.y = 0
end

function widget:update()
    -- 每个实例调用update时,操作的是自己的属性值
    self.x = self.x + 1
end

类表的核心作用是共享方法——所有实例不会重复存储这些方法,而是通过元表的__index机制指向类表,节省内存。

2. 实例的创建与使用

要得到具体的widget对象,你需要调用类的new方法(class库自动提供)来生成实例:

-- 引入类
local Widget = require "class.widget"

-- 创建两个独立的实例
local button = Widget:new()
local panel = Widget:new()

-- 初始化实例属性(调用类定义的create方法)
button:create()
panel:create()

-- 修改button的属性,不会影响panel
button.x = 100

-- 调用实例方法,各自操作自己的属性
button:update() -- button.x变成101
panel:update() -- panel.x变成1

3. 代码层面的核心差异点

  • 存储内容不同:
    • 类表:只存所有实例共享的方法,以及类级别的静态属性(比如widget.version = "1.0",所有实例都能访问,但修改的是类本身)。
    • 实例表:只存该实例独有的属性值,方法是通过元表“借”类表的,自身不存储方法。
  • self的指向不同:
    • 在类的方法里用冒号定义时,若类自己调用方法(比如widget:create()),self指向类;若实例调用(button:create()),self指向实例本身。
  • 创建方式不同:
    • 类通过class("类名")创建,是一个带元表的特殊表;
    • 实例通过类的new()方法创建,元表被绑定到类的元表,从而继承类的方法。
完整示例系统构建

结合你的需求,我完善了示例代码,让你更直观看到类和实例的运作:

class.widget.lua

local class = require "class"
local Widget = class("Widget")

-- 初始化方法(class库通常会在new时自动调用init)
function Widget:init(x, y)
    -- 每个实例独有的属性
    self.x = x or 0
    self.y = y or 0
    self.visible = true
end

-- 自定义初始化逻辑
function Widget:create()
    self.texture = "default_widget.png"
end

-- 实例更新方法
function Widget:update(dt)
    if self.visible then
        self.x = self.x + dt * 50
        self.y = self.y + dt * 20
    end
end

-- 实例绘制方法
function Widget:draw()
    if self.visible then
        print(string.format("绘制控件:位置(%d, %d),纹理%s", self.x, self.y, self.texture))
    end
end

return Widget

使用示例(main.lua)

local Widget = require "class.widget"

-- 创建两个独立实例
local button = Widget:new(100, 200)
local panel = Widget:new(300, 100)

-- 初始化实例资源
button:create()
panel:create()

-- 修改panel的属性,不影响button
panel.visible = false

-- 模拟游戏循环
for _ = 1, 3 do
    button:update(0.1)
    panel:update(0.1)
    
    button:draw()
    panel:draw()
    print("---")
end

运行后你会看到button的位置不断变化,而panel因为visible为false不会被绘制,完美体现了每个实例的独立性。

内容的提问来源于stack exchange,提问作者Shadowblitz16

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:54:38