subclassing / inheritance

I’m experimenting with some subclasses in a new implementation of my Spacewar game: there’s a common protocol for all Things in the Universe.

I was thinking to put utility functions in the Thing (primary superclass) like function Thing:capVelocity() …

I have

Ship = class(Thing)

function Ship:init()
    Thing.init(self) -- apparently cannot be written Thing:init() for some reason??
    ...
end

In the Ship class, I have a function that computes a raw velocity that it wants to cap, like this:

Function Ship:getVelocity() {
    local accel = blah blah
    local grav = blah blah
    self.vel = self:capVelocity(self.vel + accel + gravity)
}

But capVelocity() is in the superclass. The above code appears not to work. What does work is:

    self.vel = Thing:capVelocity(self.vel + accel + gravity)

That is, I have to know whether or not capVelocity is in my superclass or in my class and the syntax is different for the two cases (in the use of self vs Thing). It seems to me that this makes subclassing rather problematical and less useful than in other languages one might know.

Apparently the table for Ship does not point to and search the function table for Thing, so that superclass functions are not automatically found??

Am I missing something, or is the above the way of things? Relatedly, why does Thing.init(self) work and Thing:init() not work? I thought they were equivalent?

Thanks!

Arrgh, thought I was deleting the little example. Deleted S2. Oh well, it’s always better next time … :slight_smile:

Ah … issue is the same but somewhat obfuscated in the new Spacewar. I think.

Messages make it seem it can’t be said but load order seems to fix it. Thanks. And thanks to jmv38 for forcing me to build an example that was dumb enough to let you remind me about load order :slight_smile:

@Jmv38 I’m not faster, I probably just saw the question sooner than you did.

As he says, move the Class after Superclass.
As it is, Superclass is not known when you call it in Class. So:

Class = class(Superclass)
is equivalent (with you tab order) to
Class = class()

You say: would be nice if it would not complile. But:

Class = class() -- equivalent to:
Class = class(nil) 

are valid statements, so there is no reason for it not to compile…

damned! Dave has been faster… again!

Yes, just realized on moving the tabs. Be nice if that wouldn’t compile. But I guess it’s execution order. Now to my real problem up next. BRB

i got it.

I have been in the software industry for over a half century and have programmed at least moderately well in APL, Basic, C, C++, C#, FORTRAN, IPL-V, Java, LISP, LSL, Pascal, Ruby, Smalltalk, and surely some I have forgotten.

Nonetheless, I’m not yet grokking everything about Codea/Lua … :slight_smile:

Move Class after Superclass.

I programmed for about 35 years before I retired.

OK, here’s an example:

https://gist.github.com/RonJeffries/6e0e3856a27dc3b20b5a

Perhaps I’m doing something wrong, but I can’t even call a superclass method (inSuper) by referencing the class instance c

This isn’t even getting to my real issue yet but I must be misunderstanding something. Advise me, please …

If you want to understand the good way to use inheritance, study cargo bot example. Everything works as expected with inheritance, except the init() function of the parent class that must be called as you have done it

parent.init(self)

i’ve tried plenty of tricks to do it a more ‘natural way’, but none works. (some seem to work, but when you have multiple inheritance levels, they dont). That’s just the way to do it.
I have also noticed it is important to do things with 2 other concepts also:

  • components: add functionnalities with self.something = Something(). It is often more easy to manage compared to force some inheritance process.
  • mixin: if you want to add a component for its functions, but the call self.something.action() is really heavy and you prefer self.action(), then just copy all the function of Something() into self (except init), that works great. You can even define a class just for being mixed in, without init() function defined.
    These 2 additionnal ways are really better than inheritance in 50% of cases (better decoupling), and you must decide yourself on a case by case basis which technique is the best,

@RonJeffries this is just my personnal experienc with codea that i am sharing, learned hands on and the hard way, i am not a programmer in real life. I’ve learned OOP on this forum mainly. But i think this may help you, because that’s from the noob’s pov.

@Jmv38 just out of curiosity is anyone here a professional programmer?

I think some are.

    self.vel = self:capVelocity(self.vel + accel + gravity)
is the same as
    self.vel = self.capVelocity( self, self.vel + accel + gravity)
capVelocity, if not defined in Ship, will be looked for into Things, so that is correct

However for me the problem is that this works:
    self.vel = Thing:capVelocity(self.vel + accel + gravity)
it is equivalent to
    self.vel = self.capVelocity( Thing, self.vel + accel + gravity)
This means you are changing something for all the instances of the class???
Is this really what you want to do?
Not seeing all the code make difficult to undestand what is your pb exactly.
Ship = class(Thing)

function Ship:init()
    Thing.init(self) -- is correct
    Thing:init() -- is equivalent to Thing.init(Thing) so it changes the table Thing, not the table self, which is what you really want to do. Got it?
    ...
end