如何使用 Lua 让类 B 继承类 A?
2021-2-13 5:57:55
收藏:0
阅读:113
评论:2
我知道如何创建一个类 A:
A =
{
x = 0,
y = 0,
}
setmetatable(A, {
__call = function(self, instance)
return setmetatable(instance, { __index = A })
end
})
function A:foo1()
return string.format('Position(%d, %d)', self.x, self.y)
end
local a = A{ x = 7 } -- y will be 0 from class A
print(a.x) -- Prints 7
print(a.y) -- Prints 0
但我不知道如何让类 B 继承类 A。我希望能够在类 B 中进行自定义修改,但同时获得类 A 的所有信息。
我正在制作一个名为“战场”的事件系统,它就是类 A。我希望使用它来创建一些小游戏,比如“炸弹人”(它将是继承类 A 的类 B)、“吃豆人”(它将是继承类 A 的类 C)等等。我想要获得“战场”类的所有信息,以便在“炸弹人”和“吃豆人”中进行自定义修改,但两者之间没有关联。
例如:
B = -- B 继承自 A
{
kills = 0,
}
-- 因此 B 类会有:x、y、kills
C = -- C 继承自 A
{
deaths = 0,
}
-- 因此 C 类会有:x、y、deaths
点赞
用户8312196
我和我的朋友Kamenuvol一起研究了这个问题。
我们在寻找可读性好且易于维护的解决方案。
基于我们从Piglet的答案中所理解的,这就是最终结果:
function setClass(class, parentClass) -- (class[, parentClass])
-- class.__className is required
assert(class.__className, "Parameter '__className' is required.")
-- Set class metatable
setmetatable(class, {
__index = parentClass,
__call = function(self, instance)
return setmetatable(instance, { __index = class })
end
})
-- Attach 'is' function
class[string.format('is%s', class.__className)] = true
end
A =
{
__className = 'A',
x = 0,
y = 0,
}
setClass(A)
function A:foo1()
return string.format('Position(%d, %d)', self.x, self.y)
end
B =
{
__className = 'B',
kills = 0,
}
setClass(B, A)
function B:foo2()
return string.format('Kills(%d)', self.kills)
end
C =
{
__className = 'C',
deaths = 0,
}
setClass(C, A)
function C:foo3()
return string.format('Deaths(%d)', self.deaths)
end
D =
{
__className = 'D',
points = 0,
}
setClass(D, C)
function D:foo4()
return string.format('Points(%d)', self.points)
end
function A:foo5()
return 'Hello'
end
A.foo = 'Foo'
local a = A{ x = 7 }
print(a.x) -- 输出 7
print(a.y) -- 输出 0
print(a.kills) -- 输出 nil
print(a.deaths) -- 输出 nil
print(a.points) -- 输出 nil
print(a:foo1()) -- 输出 Position(7, 0)
local b = B{ x = 8, y = 1 }
print(b.x) -- 输出 8
print(b.y) -- 输出 1
print(b.kills) -- 输出 0
print(b.deaths) -- 输出 nil
print(b.points) -- 输出 nil
print(b:foo1()) -- 输出 Position(8, 1)
print(b:foo2()) -- 输出 Kills(0)
local c = C{ x = 9, y = 2 }
print(c.x) -- 输出 9
print(c.y) -- 输出 2
print(c.kills) -- 输出 nil
print(c.deaths) -- 输出 0
print(c.points) -- 输出 nil
print(c:foo1()) -- 输出 Position(9, 2)
print(c:foo3()) -- 输出 Deaths(0)
local d = D{ x = 10, y = 3 }
print(d.x) -- 输出 10
print(d.y) -- 输出 3
print(d.kills) -- 输出 nil
print(d.deaths) -- 输出 0
print(d.points) -- 输出 0
print(d:foo1()) -- 输出 Position(10, 3)
print(d:foo4()) -- 输出 Points(0)
print(a:foo5()) -- 输出 Hello
print(b:foo5()) -- 输出 Hello
print(c:foo5()) -- 输出 Hello
print(d:foo5()) -- 输出 Hello
print(a.foo) -- 输出 Foo
print(b.foo) -- 输出 Foo
print(c.foo) -- 输出 Foo
print(d.foo) -- 输出 Foo
print(a.isA) -- 输出 true
print(a.isB) -- 输出 nil
print(a.isC) -- 输出 nil
print(a.isD) -- 输出 nil
print(b.isA) -- 输出 true
print(b.isB) -- 输出 true
print(b.isC) -- 输出 nil
print(b.isD) -- 输出 nil
print(c.isA) -- 输出 true
print(c.isB) -- 输出 nil
print(c.isC) -- 输出 true
print(c.isD) -- 输出 nil
print(d.isA) -- 输出 true
print(d.isB) -- 输出 nil
print(d.isC) -- 输出 true
print(d.isD) -- 输出 true
2021-02-14 00:57:05
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?



继承是使用
__index实现的。请参见 https://www.lua.org/manual/5.4/manual.html#2.4
因此,每当 B 中没有实现某些功能时,您可以将索引操作引用到 A 上。
我建议您阅读一下这篇文章
http://lua-users.org/wiki/InheritanceTutorial
你可以将所有东西归结为这样的一个函数:
function CreateClass(...) -- "cls" 是新的类 local cls, bases = {}, {...} -- 将基类的内容复制到新类中 for i, base in ipairs(bases) do for k, v in pairs(base) do cls[k] = v end end -- 设置类的 __index,并开始填充一个 "is_a" 表,其中包含这个类及其所有基类, -- 这样可以使用 my_instance.is_a[MyClass] 进行“实例的”检查 cls.__index, cls.is_a = cls, {[cls] = true} for i, base in ipairs(bases) do for c in pairs(base.is_a) do cls.is_a[c] = true end cls.is_a[base] = true end -- 类的 __call 元方法 setmetatable(cls, {__call = function (c, ...) local instance = setmetatable({}, c) -- 如果有 init 方法,则运行它 local init = instance._init if init then init(instance, ...) end return instance end}) -- 返回新的类表,准备填充方法 return cls end如果您理解了这段代码,您就应该知道所有必要的东西了。