首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >B类如何与Lua一起继承A类?

B类如何与Lua一起继承A类?
EN

Stack Overflow用户
提问于 2021-02-13 05:57:54
回答 2查看 111关注 0票数 1

我所知道的是做一个这样的课程:

代码语言:javascript
复制
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‘无关的定制修改,反之亦然。

示例:

代码语言:javascript
复制
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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-02-14 00:57:05

我和我的朋友Kamenuvol一起研究这个问题。

我们正在寻找可读的可维护的

根据我们从Piglet的答案中了解到的,这是最后的结果:

代码语言:javascript
复制
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
票数 0
EN

Stack Overflow用户

发布于 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

您可以将所有的事情归结为这样的函数:

代码语言:javascript
复制
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

如果你理解这个片段,你应该知道所有必要的东西。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66182231

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档