Noob question re: Inheritance and Constructors
Monkey Forums/Monkey Programming/Noob question re: Inheritance and Constructors
| ||
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? |
| ||
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. |
| ||
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. |
| ||
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). |
| ||
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? |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
Annd.. I just had to cast it. First time for everything. Did I mention it was my first day? Honest. |
| ||
Interesting way how you do it. Did you look at the example script I have provided with the engine? |
| ||
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. |
| ||
No, I ment did you have a look at the UserDataObject.monkey script I provided with fE? |
| ||
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?" |
| ||
No problem. Just wanted to make sure that you know about this easy way of adding extra fields and methods to your objects. |