【问题标题】:Lua class inheritance problemLua类继承问题
【发布时间】:2011-10-19 03:12:44
【问题描述】:

我在 Lua 中有两个课程。一个继承另一个。

test1 = {test1Data = 123, id= {0,3}}
function test1:hello()
    print 'HELLO!'
end
function test1:new (inp)
    inp = inp or {}
    setmetatable(inp, self)
    self.__index = self
    return inp
end
test2 = {}
function test2:bye ()
    print ('BYE!', self.id)
end
function test2:new_inst_test (baseClass, inp)
    inp = inp or {}
    setmetatable(inp, self)
    self.__index = self
    if baseClass then
        setmetatable( inp, { __index = baseClass } )
    end
    return inp
end

a = test1:new({passData='abc1'})
b = test1:new({passData='ghyrty'})

c = test2:new_inst_test(a,{temp = '123343321135'})
d = test2:new_inst_test(b, {temp = '1'})



print (c.temp, c.test1Data, c.passData)
print (d.temp, d.test1Data, d.passData)
c:bye()
c:hello()

我希望 test2 不只是继承 test1,而是保存自己的方法('再见')。 可能吗? 谢谢!

【问题讨论】:

标签: oop class inheritance lua multiple-inheritance


【解决方案1】:

您应该在我认为的类元表上设置一个带有 __index=baseclass 的元表。但这会改变 test2 类中所有对象的元表。这样做,您将使用类本身的方法,并且仅在当前类中不存在该方法或它是可元的方法时才使用父类中的方法。

应该是这样的

if baseClass then
    setmetatable( self, { __index = baseClass } )
end

另一方面,在创建新实例时只指定基类,而不是在创建新类时指定基类,这有点奇怪。 所以我会重新考虑如何在类之间而不是在实例和类之间继承。

作为一个以魔法为主题的小例子:

--oop.lua Example of OOP and inheritance in Lua
Person={
    age=0,
    className='Person'
}
-- needed if needed add comparisons, operations, ...
mtPerson={}
mtPerson.__index={
    getClassName=function(self)
        return self.className
    end,
    new=function(self,t)    
        return setmetatable(t or {},{__index=self})
    end,
    inherit=function (self,t,methods)
        -- This is the heart of the inheritance: It says:
        -- Look it up in the methods table, and if it's not there, look it up in the parrent class (her called self)
        -- You pass this function the parent class (with :), a table of attributes and a table of methods.
        local mtnew={__index=setmetatable(methods,{__index=self})}
        return setmetatable(t or {},mtnew)
    end,
    introduce=function(self)
        print(("Hi! I'm %s, I'm a %s and I'm %d years old"):format(self.instanceName,self.className,self.age))
    end
    }

setmetatable(Person,mtPerson)

-- Wizard inherits from the class Person, and adds some default values and methods
Wizard=Person:inherit({
    className="Wizard",
    knownSpells={},
    },
    {
    listSpells=function(self)
        print("known spells:",self)
        if #self.knownSpells==0 then
            print'none'
        else
            for k,v in ipairs(self.knownSpells) do
                print(k,v)
            end
        end
    end
    }
)

i1=Person:new{
    inventory={'wallet'},
    instanceName="John",
}

i2=Wizard:new{ -- inherited method "new"
    inventory={'wallet','wand','cloak of invisibility'},
    instanceName="Harry",
    age=20,
    knownSpells={'Avada kavedra', 'Sesame open'}
}

i1:introduce() -- inherited method "introduce" notice that qge is the default value of 0
i2:introduce() -- 

i2:listSpells() -- method only in class 2
i1.age=26
i1:introduce()    -- changed age of instance
print(Person.age)    -- didn't change class defaults
print(Wizard.age)
i1:listSpells() -- Error.

在写这篇文章时,我得出的结论是,Lua 中的 OOP 同时非常简单,也非常复杂。您只需要在编写代码之前真正考虑清楚,然后再坚持计划。因此,这里我选择将属性放在类和实例表本身中,并将所有方法放在它们各自的元表中。我这样做是因为现在很容易遍历所有属性,而不会遇到方法,但是任何有效的选择都是有效的。你只需要选择一个。

【讨论】:

  • 我知道,它可能看起来很奇怪。我只是想有可能创建类,这将是 2 个类的“总和”(它将具有它们所有的方法和变量)
  • 如果你像我说的那样实现它,它会的。方法和变量的优先级是这样的:首先是实例的变量和方法,然后是实例所属类的变量和方法,然后是实例类继承的类的变量和方法。您唯一应该做的就是在创建类时指定继承,而不是在创建实例时。这是因为每次您指定不同的基类时,它都会在整个类范围内发生变化,而不仅仅是您正在创建的实例。
  • 你能写一个小例子吗?)我将不胜感激。因为我对 Lua 很陌生,我完全陷入了这种继承....
  • 哇!谢谢!我选择了一些不同的方法(采用来自lua.org/pil/16.3.html 的样本)。但如果我再次陷入困境,我肯定会看你的例子!
猜你喜欢
  • 1970-01-01
  • 2010-10-30
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
  • 2016-07-19
  • 1970-01-01
相关资源
最近更新 更多