Overriding Methods of Types in Modules
BlitzMax Forums/BlitzMax Programming/Overriding Methods of Types in Modules
| ||
I am currently working on a small GUI system, but am having trouble overriding methods of types that extend imported types. File 'A.bmx': Module mymod.a Public Type Something Method Do() Print "A" End Method End Type File 'B.bmx': Public Import MyMod.A Local S:Something2 = New Something2 S.Do() 'Should print B, but prints A. Type Something2 Extends Something Method Do() Print "B" End Method End Type If you run file B, it prints A instead of B, meaning the method is not overriding the module's type's method. |
| ||
What does not work ?import "basetype.bmx" Type MyType extends BaseType Method OverriddenMethod() End Method End Type works as intended. bye Ron |
| ||
Derron, I went key happy and posted half my topic by accident. I have edited to show the problem. I am overriding a module's type's method. |
| ||
Import Brl.RamStream Type TMyRamStream Extends TRamStream Method Size() print "overridden" Return _size End Method End Type global mystream:TMyRamStream = new TMyRamStream print "size: "+mystream.Size() output: ./bmk makeapp -t console -r -x "/testcodes/extendmodule.bmx" Compiling:extendmodule.bmx flat assembler version 1.68 (32768 kilobytes memory) 3 passes, 5953 bytes. Linking:extendmodule Executing:extendmodule overridden size: 0 is "B.bmx" a module too ? bye Ron |
| ||
No, file B is the end user's program. |
| ||
Appears to work as expected. In this example, it will work through different modules too, so the small example applies just the same : SuperStrict Framework brl.standardio Local S:Something = New Something S.Do() ' A Local S1:Something = New Something2 S1.Do() ' B Local S2:Something2 = New Something2 S2.Do() ' B Type Something Method Do() Print "A" End Method End Type Type Something2 Extends Something Method Do() Print "B" End Method End Type If it isn't working for you then your example does not represent the actual code you are having a problem with - I'd say you probably have a bug in your code that you don't see yet. |
| ||
Ah, I made a mistake in describing it. The Do method is being called from file A, like so: File 'A.bmx': Module mymod.a Public Type Something Method Test() Do() End Method Method Do() Print "A" End Method End Type File 'B.bmx': Public Import MyMod.A Local S:Something2 = New Something2 S.Test() 'Should print B, but prints A. Type Something2 Extends Something Method Do() Print "B" End Method End Type Sorry for the lack of intellect on my end :) |
| ||
That is something like a "scope". So when you want to have "Something2.Test()" to call the "Do()" of Something2, you have to override "Test()" too. Have had this similar in my codes. Not how we expect it to work - but there is surely a reason for such a behaviour. EDIT: ok ... tested it again, seems still to work: I edited "RamStream" to have another Method: Method MySize() Size() End Method Calling "MyRamStream.MySize()" still used the overridden Size()-Method. So dunno what does not work for you. EDIT2: Could you give a little bit more detail how you create the extended object? Maybe its "original" type is the ancestor instead of the extended one ... in that case the behaviour would be absolutely correct. bye Ron |
| ||
It worked? Well that is good news, but also bad. Good as in it works like I expected, but bad because it doesn't work on my end. I will copy my code and see if I did something wrong: Stepping through with debug only shows execution of the base "jObject" onCreate() method, even though it should be overridden. |
| ||
I copied your code. Output is: $ ./bmk makemods -a jpi Compiling:jobject.bmx flat assembler version 1.68 (32768 kilobytes memory) 3 passes, 2473 bytes. Archiving:jobject.debug.linux.x86.a ar: creating /BlitzMax/mod/jpi.mod/jobject.mod/jobject.debug.linux.x86.a Compiling:jobject.bmx flat assembler version 1.68 (32768 kilobytes memory) 3 passes, 1638 bytes. Archiving:jobject.release.linux.x86.a ar: creating /BlitzMax/mod/jpi.mod/jobject.mod/jobject.release.linux.x86.a $ ./bmk makeapp -t console -r -x "/testcodes/extendmodule2.bmx" Compiling:extendmodule2.bmx flat assembler version 1.68 (32768 kilobytes memory) 3 passes, 4006 bytes. Linking:extendmodule2 Executing:extendmodule2 MyObject Error Seems to work. |
| ||
Yes, it's a scope issue. You should probably make onCreate() in your jObject class Abstract. (which is possible if you are never likely to create an instance of jObject). Calling onCreate() frin jObject's Init() method will call the locally scoped onCreate() in preference to one in a subclass. So, something like this : Type jObject Method Init() onCreate() End Method Method onCreate() Abstract End Type |
| ||
If it works for you then it must be something on my end i'm afraid :/ Build Modules Output: Building Modules Compiling:jobject.bmx flat assembler version 1.69.14 (1048575 kilobytes memory) 3 passes, 2316 bytes. Archiving:jobject.debug.mt.win32.x86.a flat assembler version 1.69.14 (1048575 kilobytes memory) 3 passes, 4058 bytes. ar: creating C:/BlitzMax/mod/jpi.mod/jobject.mod/jobject.debug.mt.win32.x86.a Compiling:jobject.bmx flat assembler version 1.69.14 (1048575 kilobytes memory) 3 passes, 1343 bytes. Archiving:jobject.release.mt.win32.x86.a flat assembler version 1.69.14 (1048575 kilobytes memory) 3 passes, 1789 bytes. ar: creating C:/BlitzMax/mod/jpi.mod/jobject.mod/jobject.release.mt.win32.x86.a Process complete My output: Building untitled3 Compiling:untitled3.bmx flat assembler version 1.69.14 (1048575 kilobytes memory) 3 passes, 3850 bytes. Linking:untitled3.debug.mt.exe Executing:untitled3.debug.mt.exe >>"Object Error" MessageBox Here<< Process terminated Not sure what is wrong, but I guess the hunt begins. EDIT: Just saw Brucey's answer. Changing onCreate in the jObject type to abstract gives an "Unhanded Exception:Attempt to call abstract method." error. |
| ||
Which means somehow you want to call the "jobject"'s method "onCreate". Does the code you gave me work for you (or do you have more code in it) ? I freshly create a module dir for your module .. and a new example.bmx just containing the second code block you posted. This was the one that worked for me. bye Ron |
| ||
Nope, it does not work for me. I created a fresh module and used the same code, and it always wants to use the method inside the import. It is like the "Import Whatever.Mod" acts like a wall or something. Hell, I'm not even sure where to start looking for what's causing it. Is this something with MinGW? God I hope not :( |
| ||
MinGW is only used for "C". Are you using an up-to-date BlitzMax? Do you use a custom bmk/bcc (eg. Brucey "NG"-project) ? Does it happen for "non-mt-builds" too (should not change anything) ? bye Ron |
| ||
This is a fresh install of Max Version 1.50 It was installed in C:\BlitzMax, and I deleted the older version, so nothing should be bad there. I am also using the MaxIDE that came with the install. I have no third party mods other than the one I made (jpi.jobject shows up under Help>>>Third Party Modules) Yes, it happens with all builds, even non-mt and release. I'm installing a few older versions of max to see if one somehow works. *crosses fingers* |
| ||
I meanwhile tried it in my Windows setup:Building untitled1 Compiling:untitled1.bmx flat assembler version 1.69.14 (1146432 kilobytes memory) 3 passes, 3301 bytes. Linking:untitled1.exe Executing:untitled1.exe MyObject Error Process complete C:\Tools\BlitzMax\bin>bmk -v bmk 2.15 mt-win32-x86 / gcc 40601 (cpu x1) C:\Tools\BlitzMax\bin>bcc -v BlitzMax Release Version 1.48 So in this case I am using "1.48". But the only important thing in 1.50 bcc-changes was the fix of the REM-comment-bug which seems to only happen on XP machines. bye Ron |
| ||
After fiddling with constantly rebuilding all the modules, I just went and rebuild them with my older version of MinGW. Now, it overrides the correct methods for some reason (not sure how that works if anyone can explain?) One thing I did notice though is the test does not work for the new() method, like so: I am not sure if that is a bug or the New() method specifically is designed that way. I thank you for your help though guys! |
| ||
New() is different. There is, in reality, one New() method for each class, subclass, etc. When the class is instantiated, It first calls New() on its parent, which calls New() on its parent, and so on. When New() of the top-most class is called, say, your jObject, there does not exist a reference yet of a MyObject object. It calls the local onCreate() method. Here's an example of New() calling the local method : SuperStrict Framework brl.standardio Local x:C = New C Type A Method New() OnCreate() End Method Method OnCreate() Print "A" End Method End Type Type B Extends A Method New() OnCreate() End Method Method OnCreate() Print "B" End Method End Type Type C Extends B Method New() OnCreate() End Method Method OnCreate() Print "C" End Method End Type You can't use New() to call a overridden method in a subclass. |