## Object inheritance

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
zorg
Party member
Posts: 2620
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

### Re: Object inheritance

Yeah, i usually prefer to completely separate classes and instances (whether with or without any kind of inheritance is in play), to me it feels more clean, and i don't need to think about mixing both behaviours into one table, but ultimately, it's just a matter of preference.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

ivan
Party member
Posts: 1454
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: Object inheritance

Oh I think I finally understand. Here is a clearer view of the code:

Code: Select all

A = {}
function A:new()
local o = {}
setmetatable(o, self)
self.__index = self
return o
end
function A:foo()
print('A')
end
B = A:new()
function B:foo()
print('B')
end
C = B:new()
function C:foo()
print('C')
end

a = A:new()
b = B:new()
c = C:new()
a:foo()
b:foo()
c:foo()
It does work but it's just not very clear IMO.
My issue is with the merging of metatables and interfaces or "classes" into a single table.
This results in weird stuff like "self.__index = self" which is executed everytime you call "new".
In theory this line doesn't need to be executed every time you create an "instance".
I'm not crazy with modifying the metatable/interface after an object is created.
It could lead to weird bugs like:

Code: Select all

function A:new()
local o = {}
setmetatable(o, self)
self.__index = self
o:baz() -- won't work until B:baz() is defined
return o
end
B = A:new()
function B:baz()
print('B')
end

TheHUG
Citizen
Posts: 51
Joined: Sun Apr 01, 2018 4:21 pm

### Re: Object inheritance

Yes that's true about self.__index, you could set A.__index = A, and then do the same whenever you define a new class, or if you prefer to keep the metatable and the superclass separate you could define local metaA = {__index=A} and set that to be the metatable of subclasses. It's an additional thing to remember to do, and a little bit of code duplication, while the efficiency savings very small unless you spawn multiple instances per frame. I suppose you could define a function to initialize a table, set its index to the superclass you want, and define its __index attribute (or the separate metatable). I might give that a try next time.

That's a good point, if you want something in initialization to depend on something implemented by the subclass you can't do it cleanly like this. The webpage I initially got this from actually did this:

Code: Select all

function A:new(o)
local o = o or {}
setmetatable(o, self)
self.__index = self
-- more code e.g
o:baz()
return o
end

I didn't see why you may want to provide o at first, but now I can see why it might be helpful, you can do:

so that you can do

Code: Select all

B = {}
function B:baz()
print('B')
end
A:new(B)

hmm... though now I write it out I don't like the look of it. I'll play around with that more if I run into a situation where I want some part of initialization to depend on a method of the subclass.

edit:

Code: Select all

B = A:new({
baz=function(self)
...
end})

looks alright to me

ivan
Party member
Posts: 1454
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: Object inheritance

The most confusing part is that you're doing multiple things through the :new() function.
I would split that into two functions: :new() and :inherit() then the code would look much more clear.

TheHUG
Citizen
Posts: 51
Joined: Sun Apr 01, 2018 4:21 pm

### Re: Object inheritance

That's a pretty good idea

pgimeno
Party member
Posts: 1690
Joined: Sun Oct 18, 2015 2:58 pm

### Re: Object inheritance

That's indeed the approach that 4vZEROv posted in the previous page (except 'inherit()' is called 'extend()' in 4vZEROv's version).

raidho36
Party member
Posts: 1804
Joined: Mon Jun 17, 2013 12:00 pm

### Re: Object inheritance

In my class implementation, inheritance workflow is set up like this:

Code: Select all

local baseclass = Class ( "baseClassName" )
function baseclass:foo ( ) ...
local derivedclass = baseclass:extend ( "derivedClassName" )
function derivedclass:bar ( ) ...
Internally, it copies over all data from base class into derived class. Not having to do multiple __index hops to find inherited functions and values makes it run a lot faster, and the memory footprint increase is microscopic (it's only the class definition, not individual instances). However, this also means that it won't pick up changes made to the base class after the inheritance call, so one should only inherit from complete classes.

### Who is online

Users browsing this forum: Bing [Bot], Exabot [Bot] and 3 guests