Lua类继承问题。

我在 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,而且还保存自己的方法('bye')。这是可能的吗? 谢谢!

原文链接 https://stackoverflow.com/questions/6927364

点赞
stackoverflow用户513763
stackoverflow用户513763

我认为你应该在类元表中设置一个带有 __index=baseclass 的元表。但这将改变测试2类中所有对象的元表。通过这种方式,你将使用类本身的方法,并且仅在当前类中不存在该方法或其元表时才使用父类的方法。

所以应该像这样:

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

另一方面,仅在创建新实例时指定 baseclass 而不是在创建新类时指定,有点奇怪。因此,我会重新思考如何在类之间继承,而不是在实例和类之间继承。

下面是一个小的巫师主题示例:

--oop.lua  Lua 中面向对象编程和继承的示例
Person={
    age=0,
    className='Person'
}
-- 需要使用,如果需要添加比较、操作等...
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)
        -- 这是继承的核心:它说:
        -- 在 methods 表中查找它,如果它不在,就在父类中 (这里称为 self) 查找。
        -- 你需要通过 : 将此函数传递给父类(一个表的形式),一些属性表和方法表。
        local mtnew={__index=setmetatable(methods,{__index=self})}
        return setmetatable(t or {},mtnew)
    end,
    introduce=function(self)
        print(("嗨!我是%s, 我是一个%s,今年%d岁"):format(self.instanceName,self.className,self.age))
    end
    }

setmetatable(Person,mtPerson)

-- Wizard 从类 Person 继承,并添加一些默认值和方法
Wizard=Person:inherit({
    className="Wizard",
    knownSpells={},
    },
    {
    listSpells=function(self)
        print("已知咒语:",self)
        if #self.knownSpells==0 then
            print'无'
        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{ -- 继承的方法 "new"
    inventory={'wallet','wand','cloak of invisibility'},
    instanceName="Harry",
    age=20,
    knownSpells={'Avada kavedra', 'Sesame open'}
}

i1:introduce() -- 继承的方法 "introduce",请注意年龄是默认值 0
i2:introduce() --

i2:listSpells() -- 仅在类 2 中的方法
i1.age=26
i1:introduce()    -- 实例年龄更改
print(Person.age)    -- 未更改类的默认值
print(Wizard.age)
i1:listSpells() -- 错误。

在编写此代码时,我得出的结论是 Lua 中的面向对象编程既非常简单,又非常复杂。在编写代码之前,你必须仔细考虑,然后在计划之后坚持。因此,在这里,我选择将属性放在类和实例表中,并将所有方法放在各自的元表中。我这样做是因为现在可以轻松地遍历所有属性,而不会遇到方法,但任何有效的选择都可以。你只需要选择一种。

2011-08-03 14:18:26