Object inheritance

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Schwender.exe
Prole
Posts: 25
Joined: Mon Oct 16, 2017 6:07 pm
Location: the moon
Contact:

Object inheritance

Post by Schwender.exe »

for a while I hopped over to C# (while trying out unity) and after not enjoying the language and engine, I came back to lua. Ever since then I've been learning to do oop in lua, however one issue I've run into is inheritance, I somewhat solved one half of inheritance with functions and variables carrying over to the child objects, however I can't seem to get one feature working, that being inheriting parent functions without overwriting them.
here's the code I have for the base object:

Code: Select all

-- in entity.lua
local Entity = { -- base table with all variables for the entity object
  pos = { x=0,y=0 },
  dx=0,dy=0,
  name="",
  stunTimer = 0,
}
-- -- --
Entities = {} -- global table where all entities are stored
-- -- --
function Entity.new( vars )
  local entity = setmetatable( table.copy( Entity ), { __index = Entity } ) -- creates entity metatable
  for i,v in pairs( vars ) do entity[i] = v end -- takes variables from vars table and moves variables to entity
  table.insert( Entities, entity ) -- adds entity to table of all entities ( easier to destroy )
  return entity
end
-- -- --
function Entity:update( dt ) -- base update, I want to change so this can be called from any children who inherit entity
  print( "entity \""..self.name.."\" does not have an update function!" )
  -- ^ will change code once I get this working
end
and some example code from the player object

Code: Select all

-- in player.lua
local Player = { -- base table with all player variables
  isPlayer = true,
  HP = 0, MAXHP = 3,
  canMove = true,
  moving = false,
  direction = "right",
}
-- -- --
function Player.new()
  return ENTITY.new( Player )
end
-- -- --
function Player:update( dt )
  -- where I want to call the update function of the 'base' object, entity
end
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: Object inheritance

Post by raidho36 »

You simply inherit from the base class without defining the child's function, then it'll use base class function.

However, inheritance has inherent problems to it that aren't easy to solve, and it doesn't offer any particular advantages over other methods. Which is to say, you should use "mixin" paradigm instead, where you simply add other classes' fields and methods to your new class.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Object inheritance

Post by ivan »

Hello there.
I think the easiest way to do inheritance is by using metatables.
We don't copy tables/variables when using metatables - that's the whole point.
There are more fancy libs out there that can do more sophisticated things,
but if you are looking for inheritance alone this is one way to do it:
https://github.com/2dengine/oo.lua
Last edited by ivan on Sat Dec 11, 2021 8:24 am, edited 1 time in total.
TheHUG
Citizen
Posts: 61
Joined: Sun Apr 01, 2018 4:21 pm

Re: Object inheritance

Post by TheHUG »

There's more than one way to do this in lua, and rather than use a library implementing classes I prefer to do it explicitly, since its just a few lines. One of the things I like about lua is that unlike a lot of other scripting languages it doesn't pretend to have true classes, which lets you use the flexibility of its system without needing to learn the intricacies of its class implementation. (for example changing of instance methods in python for example requires a bunch of messing around with MethodTypes and hasattr, etc., while in lua its just standard table operations).

I like:

Code: Select all

object={}
function object:new()
    local o = {}
    self.__index = self
    return setmetatable(o, self)
end
then:

Code: Select all

subclass = object:new()

function subclass:somemethod()
    ...
end

then `object:new` creates a table that inherits from object.subclass is both an instance of object, and since it inherits the `:new` method it can also be a 'class' to base other objects on. So subclass:new creates an instance of subclass, which then inherits the somemethod() method from it.
Last edited by TheHUG on Mon Jul 08, 2019 12:18 pm, edited 1 time in total.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Object inheritance

Post by ivan »

Your example requires closures (somemethod) for the inheritance to work. That's still copying stuff around. Using just metatables would work better in this case.
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Object inheritance

Post by pgimeno »

To call a method in the parent class, you can use getmetatable(self).update(self, dt), or you can define a 'parent' property which is set in Player.new and call it with self.parent.update(self, dt). You can probably abstract these things out in a library.

I don't see a clear distinction between classes and instances in your code. That's not good.
User avatar
Schwender.exe
Prole
Posts: 25
Joined: Mon Oct 16, 2017 6:07 pm
Location: the moon
Contact:

Re: Object inheritance

Post by Schwender.exe »

pgimeno wrote: Sat Jul 06, 2019 7:45 pm I don't see a clear distinction between classes and instances in your code. That's not good.
what do you mean exactly by that, I'm somewhat new to object inheritance
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: Object inheritance

Post by raidho36 »

He means that class definitions look like instance definitions - which I don't think they do. The "not good" is his personal opinion on the matter.
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Object inheritance

Post by pgimeno »

Yeah, sorry. The structure seems to be fine, it just confused me a bit.
TheHUG
Citizen
Posts: 61
Joined: Sun Apr 01, 2018 4:21 pm

Re: Object inheritance

Post by TheHUG »

ivan wrote: Sat Jul 06, 2019 12:28 pm Your example requires closures (somemethod) for the inheritance to work. That's still copying stuff around. Using just metatables would work better in this case.
Hmm, I think you misunderstand, :somemethod is a method of childobject. Whenever you create a new childobject with childobject:new, it will not have a copied :somemethod, but references childobject via the __index metamethod.

my naming there was confusing, sorry. I'll update the code to be clearer
Post Reply

Who is online

Users browsing this forum: Google [Bot], Mathisto and 49 guests