类与实例的区别是什么?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
相关产品推荐
相关产品推荐

