Super.Super not valid
BlitzMax Forums/BlitzMax Programming/Super.Super not valid
| ||
bummer. I wanted to call Super.Super.Manage() to call Manage from my based type, not the type in the middle. (I've extended twice from the base type). Doesn't seem like you can typecast super either. I tried typecasting Super to the basetype and calling manage but that failed with a memory access violation e.g. TDialog(Super).Manage() This fails with the same error: TDialog(Self).Manage() I don't want to make a BaseClassManage() method or something lame. Any other ideas? thx. |
| ||
Type A method MyMethod() end method end type Type B extends A end type Type C extends B end type Local myType:C = C new. A(C).MyMethod() not tested as I'm not on my dev machine at the moment. Blitzmax doesn't support overloading methods last I recall so why would calling the super method help? Or am I mis-understanding the issue (due to lack of context). |
| ||
I have all my objects' hierarchy such that I only ever use Super in chains, like the new() and delete() methods. In other words : eg: Type firstleveltype Method Manage() ' FIRST LEVEL STUFF HERE '/FIRST LEVEL STUFF HERE End Method End Type Type secondleveltype Method Manage() Super.Manage() ' SECOND LEVEL STUFF HERE '/SECOND LEVEL STUFF HERE End Method End Type Type thirdleveltype Method Manage() Super.Manage() ' THIRD LEVEL STUFF HERE '/THIRD LEVEL STUFF HERE End Method End Type So it chains back up through the type derivations. |
| ||
Gabriel, I think that's what Grey was trying to avoid. He wanted to 'skip' the 2nd level if I understood correctly. Which to me sounds like a possible design issue. |
| ||
Store a reference to the object in a static variable in a public function which returns the object in question. Using that function, you can call the method from anywhere without having to go through the class tree. |
| ||
Gabriel, I think that's what Grey was trying to avoid. He wanted to 'skip' the 2nd level if I understood correctly. I thought so too, but wasn't 100% sure. I posted the code example just to clarify. My main point was that I think objects should be planned such that skipping isn't required. Which to me sounds like a possible design issue. I agree. For me, inheritance says "Object B does everything that Object A does, plus some other stuff." If Object B doesn't do everything Object A does, it either shouldn't inherit from Object A, or another tier may be required inbetween, perhaps with abstract methods if it's just an implementation issue you want to skip, rather than a functional issue. |
| ||
Yeah I was trying to avoid the 2nd level stuff. It's probably bad design but like all these things, makes a lot of sense right now. So how to you say Object B inheritcs from Object A and Object C inherits from Object B but a few things in Object C are different rather than simply extended... Winni. Yeah good point. In the end I made a ManageCore() method and called that instead. |
| ||
why do you want to do that? if you really are thinking oop (no offense) you should never need super.super., you should always rely on what you extended from. which is ok since the second fully extends, has all methods and abilities of the first. it's easy to want to do this when you are doing all the coding for all the classes but you should try(always) to keep you extended type only knowing it's parent. so you should either do type first method manage() end method end type type second extends first end type type third extends second method manage() blah super.manage end method end type or add a manage method in the second... method manage() blah super.manage end method |
| ||
So how to you say Object B inheritcs from Object A and Object C inherits from Object B but a few things in Object C are different rather than simply extended... Well that's hard to answer without at least an abstract example of how it's different. Different implies it just implements things in a different manner in which case you either want Abstract methods in Object A ( if Object A is never instantiated ) or you want overridden methods in Objects B and C, but that doesn't really explain wanting to skip somethiing, so that's probably not what you mean by different. Does it do less? Does it do more? What makes it different? If it at least does everything that ObjectA does, then you could have it extend ObjectA and move everything which B and C both do up the hierarchy into Object A, and then make those new methods abstract so that Objects B and C have to implement them. This. of course, assumes that Object A is an abstract object which you never instantiate - which may or may not be the case. |
| ||
I think Super is a compiler 'in scope' directive. It points to the underlaying extended type instance of an object and allows you to call its methods. As long a super is not a method, super.super is not allowed. |
| ||
Yeah basically Object A is TDialog and it's Abstract. Object B is a TDialogYesNo. Both have a Manage() method. B.Manage() calls Super.Manage() and that's fine. So I wanted an Object C which was a variant of TDialogYesNo with different buttons and text layout BUT I can't alter Object B (TDialogYesNo) because it's part of my framework and other people need it. B.Manage() won't work properly for my new Object C, so I needed to call A.Manage() then some extra code for the new Object C. Sometimes the problem with design is that once you've made something and released it to the public, you can't really go and change the way it works in a big way or you break their code. It's not the same as sitting down and designing everything from scratch OR being able to refactor your design later. You *can* change the way it works internally though and that's why I added a ManageCore() method to Object A which A.Manage() calls. Then in C.Manage() I call ManangeCore and then my own code, which works fine because Object B doesn't override A.ManageCore() only A.Manage(). Make sense? |
| ||
In the instance you've descibed, I'd create a new (abstract) type called TDialogBasicYesNo, and have the existing TDialogYesNo extend that. Then have TDialogAdvancedYesNo ( or whatever the new one will be called ) also extends TDialogBasicYesNo. Now you have some breathing room in what TDialogAdvancedYesNo and TDialogYesNo do because their manage methods are not related. Anything they still have in commmon can be shifted up to TDialogBasicYesNo and you haven't made any changes to TDialogYesNo, so your users can continue to use it as they are, completely unaware of any changes you've made. It's an extra level of abstraction which I would normally try to avoid, but if you have to keep things unchanged for people who are already using the module, there has to be a price to pay somewhere. |
| ||
very good. I like it. It's 2am, surprise you can think straight ;-) I'm wired on Cola as I've just been to watch Die Hard 4.0. |
| ||
what Gabriel said.... or you could do what we've seen before like in the win32 api and such... create a new TDialogYesNoEx which extends from TDialog with all your new stuff. or sometimes when I have some function or method that I need to keep future proof but still compatible I use a TMap for the params or just a plain type that I can always add more fields to. |
| ||
You could as well just do TDialog(self).blabla instead of using some strange stuff, if you know to which base class you actually wanted to jump anyway :) |
| ||
That didn't work, I already tried it (and mentioned it in the first post). |
| ||
hmm must have missed the part with self. that super does not work is clear, its no object. But as self can be returned, I was under the assumption that it actually should work on self. |
| ||
Yep exactly what I thought but it gives and access violation. Self doesn't seem to be working quite the same as a normal object... |
| ||
did you try to fake? Just got an idea which perhaps works: Method GetSelf:object() return self End Method and then try to cast this one? *if it works then self definitely needs to be fixed ... if it does not work, just return an input argument "obj:Object" which you return ... at latest at that point it will work* |
| ||
I would personnaly just go for Gabriel's solution rather than trying to do a fancy workaround which may work now but in the future might get 'fixed' which would break your code. Its seems your Type C is not an actual extension of Type B. Its more like they are 'siblings' !?. Therefore logically speaking you should have a type BC which extends Type A containing all the common code. Then Type B and C are extensions of Type BC with unique implementations of the Manage() method. Of course its easy to say this from where Im sitting... I dont have a deadline to hit. Good luck |
| ||
Dreamora: haha no I never tried that. QuietBloke: Yeah BC would make sense. Like I said I got round it with a ManageCore() method. Bit of a cheat but its fine. |
| ||
If casting to call the base method worked that would defeat the purpose of the vtable. The vtable is there so the correct method gets called on the current instance. |
| ||
You can't be completely assured what the type you are derived from is derived from. You can only be certain about that one Super, because Super's Super could in theory be changed to something else. Okay, dumb thought... |