Noob question re: Inheritance and Constructors

Monkey Forums/Monkey Programming/Noob question re: Inheritance and Constructors

Kauffy(Posted 2012) [#1]
Something I'm confused about and I'm not sure I can explain it well.

When you create a new class that extends another class, and call a constructor for the subclass, is the superclass's constructor called automatically, or only when explicitly called with Super.New (for example)?

More to my point, I am using Mike Hartlef's fantomEngine for a small project.

I have created a class that extends ftObject (I wanted my objects to be available in his engine's callbacks).

When I call my constructor, I can initialize my portion of the object (i.e., my new, extended fields), but the ftObject is intended to be initialized with a Method call on the engine itself-- for example: engine.CreateImage:ftObject(imagename, etc., etc.)

Here's where the extra confusion is: is it possible to call a method that creates an instance of a superclass of the constructor we're in-- and have it be this object (or the inherited part of this object)? This is one of those make-my-brain-hurt situations.


If anyone has any idea what I'm talking about, is there an alternate approach recommended?


Rone(Posted 2012) [#2]
Hi,

the default constructor is called automatically, if you do not call any superclass's constructors.

Since fantomEngine's ftObejct class does not implement any constructors, you need to init ftObejct manually in classes derived from ftObejct.

do not know if it is even being considered to derive from ftObject, because the interface seems not really designed to derive from ftObject.


MikeHart(Posted 2012) [#3]
Rone is right here. I will think about how it could be done. For the moment you can use the new data object for more individuality here.


Kauffy(Posted 2012) [#4]
What I have done is gone back to including an ftObject within my object, instead of deriving. Then I am packing the superclass info I need into the ftObject in its CollGroup and in the .tag field.

So, I have Tank objects that can either be player (1-4) or enemy (infinity!).
I have a player object, then contains player-specifics (score, key layout, etc.) AND it contains a tank object.

For enemy, it contains enemy specifics (AI objective, a few other things) AND it contains a tank object.

When I call my New Tank, I pass in two args: isPlayer:bool, and num:Int.

If isPlayer is true, then we build the tank for the player, and the num argument contains the player # (determines start position and which image to use for the tank.)

If isPlayer is false, the we build the tank for the enemy, and the num argument contains the level of enemy it is (determines speed, hitpoints, weapon type, etc.)

Double-purposing the CollGroup to tell me what type of thing it is, AND using ftObject.tag to tell me either player number or enemy level has allowed me to take appropriate action in the callbacks.

So, when I get a callback from a given Tank's ftObject, I know what type of thing it is (Player, Enemy, Playershot, etc.) and then which player, or what level of enemy, etc. it is.

This makes writing the OnObjectUpdate part of ftEngine's BaseScript pretty snappy!


The problem I was having was how to instantiate a derived ftObject, but I worked around it by going away from "is a type of" to "owns an instance of" (I still struggle to wrap my head around some of these things).


MikeHart(Posted 2012) [#5]
you can also use the new data object for storing extra info inside an object.

so you are storing an object inside the colgroup property? How?


Kauffy(Posted 2012) [#6]
I will look at the data object to see how that could work.

I did not store an object in ColGroup, just using the ColGroup to represent both the collision group and, by reading the collision group, knowing what kind of object it is. In this case, it works perfectly for my needs-- though I could see situations in the future where that wouldn't be the case.

I then just used ftObject.tag to store an int, as it looks like ftObject.tag isn't used anywhere else.


Kauffy(Posted 2012) [#7]
I looked at using ftDataObject--

I wound up declaring like this...

Class Player
  field tank:Tank
.
.
.

Class Tank
  field gob:ftObject
.
.
.

Method Player.New()
  Self.tank = New Tank()

  Self.tank.gob.SetDataObj = Self 'Seems weird, but I guess it's just pointing back up the tree to itself.



I will see how this works.


Kauffy(Posted 2012) [#8]
Ahh.. even though it lets me set the DataObj to any type, when I try to do the reverse, I get a "Cannot convert from object to Enemy." error.


Kauffy(Posted 2012) [#9]
Annd.. I just had to cast it. First time for everything.

Did I mention it was my first day? Honest.


MikeHart(Posted 2012) [#10]
Interesting way how you do it. Did you look at the example script I have provided with the engine?


Kauffy(Posted 2012) [#11]
Yes. I'm using the Base Script.

What I'm doing is that I have a variety of Tanks (some player, some enemy).

In order to know what to do with them when OnObjectUpdate gets called, I need to know which one it is.

Since OnObjectUpdate gets called on ftObjects, I needed a way, from within the ftObject, to be able to reference either the Player or Enemy that "owns" this Tank.


MikeHart(Posted 2012) [#12]
No, I ment did you have a look at the UserDataObject.monkey script I provided with fE?


Kauffy(Posted 2012) [#13]
Oh, oh! I didn't realize those were in there. Let me go and take a look.

EDIT: Oh, yes, I did actually read through this. In my case, I am pointing to the ftObject's owner's (Class Tank) owner (Class Player), so I can not create the data object at the time I am creating the ftObject.

There may be a way to achieve what I'm doing with reflection, but I think that will add too much bulk and I don't want to take the detour to understand it if it isn't necessary. I just need a way to ask the ftObject "Who is your daddy, and what does he do?"


MikeHart(Posted 2012) [#14]
No problem. Just wanted to make sure that you know about this easy way of adding extra fields and methods to your objects.