我所知道的是做一个这样的课程:
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类),Pacman (它将是继承A类的C类),等等。我想得到所有的东西,从‘战场’类,使‘轰炸机’和‘帕克曼’与它。然后在“轰炸机”中做一些与'Pacman‘无关的定制修改,反之亦然。
示例:
B = -- B inherits A
{
kills = 0,
}
-- So B class would have: x, y, kills
C = -- C inherits A
{
deaths = 0,
}
-- So B class would have: x, y, deaths

发布于 2021-02-14 00:57:05
我和我的朋友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) -- Prints 7
print(a.y) -- Prints 0
print(a.kills) -- Prints nil
print(a.deaths) -- Prints nil
print(a.points) -- Prints nil
print(a:foo1()) -- Prints Position(7, 0)
local b = B{ x = 8, y = 1 }
print(b.x) -- Prints 8
print(b.y) -- Prints 1
print(b.kills) -- Prints 0
print(b.deaths) -- Prints nil
print(b.points) -- Prints nil
print(b:foo1()) -- Prints Position(8, 1)
print(b:foo2()) -- Prints Kills(0)
local c = C{ x = 9, y = 2 }
print(c.x) -- Prints 9
print(c.y) -- Prints 2
print(c.kills) -- Prints nil
print(c.deaths) -- Prints 0
print(c.points) -- Prints nil
print(c:foo1()) -- Prints Position(9, 2)
print(c:foo3()) -- Prints Deaths(0)
local d = D{ x = 10, y = 3 }
print(d.x) -- Prints 10
print(d.y) -- Prints 3
print(d.kills) -- Prints nil
print(d.deaths) -- Prints 0
print(d.points) -- Prints 0
print(d:foo1()) -- Prints Position(10, 3)
print(d:foo4()) -- Prints Points(0)
print(a:foo5()) -- Prints Hello
print(b:foo5()) -- Prints Hello
print(c:foo5()) -- Prints Hello
print(d:foo5()) -- Prints Hello
print(a.foo) -- Prints Foo
print(b.foo) -- Prints Foo
print(c.foo) -- Prints Foo
print(d.foo) -- Prints Foo
print(a.isA) -- Prints true
print(a.isB) -- Prints nil
print(a.isC) -- Prints nil
print(a.isD) -- Prints nil
print(b.isA) -- Prints true
print(b.isB) -- Prints true
print(b.isC) -- Prints nil
print(b.isD) -- Prints nil
print(c.isA) -- Prints true
print(c.isB) -- Prints nil
print(c.isC) -- Prints true
print(c.isD) -- Prints nil
print(d.isA) -- Prints true
print(d.isB) -- Prints nil
print(d.isC) -- Prints true
print(d.isD) -- Prints true发布于 2021-02-13 10:00:53
继承是使用__index实现的。
请参阅https://www.lua.org/manual/5.4/manual.html#2.4
__index:索引访问操作表键。当表不是表或表中没有键时,就会发生此事件。这个元雪崩是在桌子的中间层向上看的。此事件的元雪崩可以是函数、表,也可以是带有__index元雪崩的任何值。如果它是一个函数,则以表和键作为参数调用它,调用的结果(调整为一个值)是操作的结果。否则,最后的结果是用键索引这个元值的结果。这个索引是规则的,而不是原始的,因此可以触发另一个__index元雪崩。
因此,无论什么东西在B中没有实现,您都可以将索引操作引用到A。
我建议你给我看一下
http://lua-users.org/wiki/InheritanceTutorial
您可以将所有的事情归结为这样的函数:
function CreateClass(...)
-- "cls" is the new class
local cls, bases = {}, {...}
-- copy base class contents into the new class
for i, base in ipairs(bases) do
for k, v in pairs(base) do
cls[k] = v
end
end
-- set the class's __index, and start filling an "is_a" table that contains this class and all of its bases
-- so you can do an "instance of" check using 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
-- the class's __call metamethod
setmetatable(cls, {__call = function (c, ...)
local instance = setmetatable({}, c)
-- run the init method if it's there
local init = instance._init
if init then init(instance, ...) end
return instance
end})
-- return the new class table, that's ready to fill with methods
return cls
end如果你理解这个片段,你应该知道所有必要的东西。
https://stackoverflow.com/questions/66182231
复制相似问题