Lua使用classic库扩展类时实例属性被覆盖的原因
问题原因与解决办法
你的代码出现实例属性互相覆盖的核心原因是:子类构造函数调用父类构造时,错误地把父类本身作为self传入,导致父类的类属性被修改,所有子类实例共享了这些父类属性。
具体问题分析
在classic库中,:new()语法会自动将调用者作为第一个参数(也就是self)传入方法。你写的NonPair.super:new(1, 2)等价于NonPair.super.new(NonPair.super, 1, 2)——这里的self是父类Combination本身,而不是你创建的NonPair实例。
这就导致:
- 创建
NonPair实例时,父类Combination的level和score被设置为1和2; - 创建
OnePair实例时,父类的level和score又被覆盖为1和3; - 子类实例如果没有自己的属性,会向上查找父类的属性,所以两个实例的
level都会变成最后一次修改的父类值。
正确写法
子类构造函数调用父类构造时,必须将当前子类实例的self传入父类的new方法,用点调用(.)而不是冒号调用(:):
Combination = Object:extend() function Combination:new(level, score) self.curentCombinationValues = 0 self.curentCombination = {} self.level = level self.score = score end NonPair = Combination:extend() function NonPair:new() -- 将当前实例self传入父类构造 NonPair.super.new(self, 1, 2) end OnePair = Combination:extend() function OnePair:new() OnePair.super.new(self, 1, 3) end
或者更通用的写法,用self.super来指代父类,避免硬编码类名:
function NonPair:new() self.super.new(self, 1, 2) end
这样修改后,父类构造函数操作的是每个子类实例自己的self,属性会被初始化在实例独立的空间里,不同实例的属性就不会互相覆盖了。
内容的提问来源于stack exchange,提问作者Андрей Дов
相关产品推荐
相关产品推荐

