开发者

Lua class inheritance problem

开发者 https://www.devze.com 2023-03-25 04:01 出处:网络
I have two classes in Lua. One inherits another. test1 = {test1Data = 123, id= {0,3}} function test1:hello()

I have two classes in Lua. One inherits another.

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,{tem开发者_如何学JAVAp = '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()

I want test2 not just inherit test1, but save own methods ('bye'). Is it possible? Thanks!


you should set a metatable with __index=baseclass on the class metatable I think. But that will change the metatable for all objects in the test2 class. Doing it this way, you will use the methods from the class itself, and only use methods from the parent when the method does not exists in the current class, or it's metatable.

So it should be like

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

On the other hand it's kind of weird that you only specify the baseclass when making a new instance, instead of specifying it when creating the new class. So I'd rethink how you inherit between classes instead of between instances and classes.

As a small wizardry themed example:

--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.

While writing this, I came tho the conclusion that OOP in Lua is at the same time very simple, and very complicated. You simply have to really think things through before writing code, and stick with the plan afterwards. As such, here I chose to put attributes in the class and instance tables themselves, and put all methods in their respective metatables. I did this because now it's easy to iterate through all attributes, without encountering methods, but any choice that works is valid. You just have to pick one.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号