About Monkey 2 › Forums › Monkey 2 Programming Help › Extending classes and Override question
This topic contains 11 replies, has 4 voices, and was last updated by 
 wiebow
 2 years, 10 months ago.
- 
		AuthorPosts
 - 
		
			
				
June 12, 2016 at 9:24 pm #1083
Hello,
I have a question regarding extending classes and overriding methods. In BlitzMax, in a base Type, I was able create and for instance, call that empty method in the New() method. In the extended type, I would override that method. Creating a new extended would result in the method being called automatically because the the base type New() method would would call it.
Now in M2, I try the following:
Monkey1234567891011121314151617181920212223242526272829303132333435363738394041424344'using mojo to make stuffNamespace test#import "<std>"#import "<mojo>"Using std..Using mojo..Function Main:Void()New TestPrint( "done" )End FunctionClass Test Extends Game2dMethod New()Print( "new in test" )End MethodMethod Startup:Void() OverridePrint( "startup in test" )End MethodEnd ClassClass Game2dMethod New()Print( "new in game2d" )Self.Startup()Start()End MethodMethod Start:Void()Print( "start in game2d" )End Method#Rem monkeydoc Hook for user startup code.#EndMethod Startup() VirtualPrint( "startup in game2d" )End MethodEnd ClassI expected the extended version of Startup being called, but instead the base version is called. This is different than how it was in Max.. Is this intended behaviour? And if so, does anyone have an idea to emulate ‘hooks’ ?
I really liked this feature as it was really simple to call code automatically.
Thanks!
June 12, 2016 at 11:40 pm #1084This looks like a bug to me. In most languages the extended version of startup should be called…
Java:
[/crayon]Monkey1234567891011121314151617181920212223242526272829303132333435[crayon-5cb9bd63a1ac7946682640 inline="true" ]class Testing {public static void main(String[] args) {Testing t = new Testing();}public Testing() {Test c = new Test();}private class Test extends Game2d{public Test() {System.out.println("Test - Ctor...");}public void startup() {System.out.println("Test - startup");}}private class Game2d {public Game2d() {System.out.println("Game2d - Ctor...");this.startup();start();}public void start() {System.out.println("Game2d - start");}public void startup() {System.out.println("Game2d - startup");}}}Outputs:
[/crayon]Monkey1234[crayon-5cb9bd63a1acd248327588 inline="true" ]Game2d - Ctor...Test - startupGame2d - startTest - Ctor...MX1:
[/crayon]Monkey1234[crayon-5cb9bd63a1ad2314878826 inline="true" ]Game2d - CtorTest - startupGame2d - startTest - CtorMX2:
[/crayon]Monkey1234[crayon-5cb9bd63a1ad7006662865 inline="true" ]Game2d - CtorGame2d - startupGame2d - startTest - CtorJune 13, 2016 at 2:07 am #1085> In most languages the extended version of startup should be called…
Well, most languages except c++ (and I think Java gives an error).
A bit more on this here:
http://www.monkey-x.com/Community/posts.php?topic=10557
I actually haven’t decided 100% which way I’m going here either.
June 13, 2016 at 4:28 am #1086[quote]Well, most languages except c++ (and I think Java gives an error).[/quote]
Well I always thought C++ was a bit odd
Java outputs:
[/crayon]Monkey1234[crayon-5cb9bd63a8c6a341289525 inline="true" ]Game2d - Ctor...Test - startupGame2d - startTest - Ctor...Run the code in the above post, pure Java and no errors…
June 13, 2016 at 4:51 am #1087Playing with C#, using override and virtual:
[/crayon]Monkey123456789101112131415161718192021222324252627282930313233[crayon-5cb9bd63ab14a739441415 inline="true" ]using System;namespace test{class Program{public static void Main(string[] args){new Test();Console.ReadKey(true);}}class Test:Game2d {public Test() {Console.WriteLine("Test ctor");}public override void startup() {Console.WriteLine("Test startup");}}class Game2d {public Game2d() {Console.WriteLine("Game2d ctor");this.startup();}public virtual void startup() {Console.WriteLine("Game2d startup");}}}Outputs:
[/crayon]Monkey123[crayon-5cb9bd63ab151020078239 inline="true" ]Game2d ctorTest startupTest ctorNot using override and virtual keywords:
[/crayon]Monkey123456789101112131415161718192021222324252627282930313233[crayon-5cb9bd63ab156281209706 inline="true" ]using System;namespace test{class Program{public static void Main(string[] args){new Test();Console.ReadKey(true);}}class Test:Game2d {public Test() {Console.WriteLine("Test ctor");}public void startup() {Console.WriteLine("Test startup");}}class Game2d {public Game2d() {Console.WriteLine("Game2d ctor");this.startup();}public void startup() {Console.WriteLine("Game2d startup");}}}Outputs:
[/crayon]Monkey123[crayon-5cb9bd63ab15a830591905 inline="true" ]Game2d ctorGame2d startupTest ctorJune 13, 2016 at 4:59 am #1088Ok, looks like c++ enforces it, but other languages only warn about it:
http://stackoverflow.com/questions/3404301/whats-wrong-with-overridable-method-calls-in-constructors
https://msdn.microsoft.com/en-us/library/ms182331.aspx
I think it’s generally a good rule – if a ctor calls a method that is overridden by a subclass, that method can no longer depend on it’s class fields being properly initialized because it’s ctor hasn’t been executed yet. Or just as bad, the override could be called, but then anything it did gets undone by the ctor being called later, eg:
But I’ll likely end up sticking with what’s most practical/flexible on the translator side of things.
June 13, 2016 at 5:40 am #1089Just fired up Code::Blocks (last time I used that when I was testing the BMX 3D stuff!):
[/crayon]Monkey12345678910111213141516171819202122232425262728293031323334353637383940414243[crayon-5cb9bd63b43f6247575185 inline="true" ]#include <stdio.h>class Game2d{public:Game2d(){printf("Game2d ctor\n");startup();start();}void start(){printf("Game2d start\n");}virtual void startup(){printf("Game2d startup\n");}};class Test: public Game2d{public:Test(){printf("Test ctor\n");}virtual void startup(){printf("Test startup\n");}};int main(){Test g;return 0;}Outputs:
[/crayon]Monkey1234[crayon-5cb9bd63b440a464786154 inline="true" ]Game2d ctorGame2d startupGame2d startTest ctorSo as long as what MX2 is going to do is well defined and documented I dont think we can complain too much
June 13, 2016 at 7:42 am #1090Nope, thanks for investigating this! It’s good to know and understand that some of the ways of working in Max are not valid anymore.
June 13, 2016 at 1:48 pm #1092so how do you access the method in the extended class are we still using the extended Class?
June 13, 2016 at 2:40 pm #1093You can access it, but only from the extended class, not from the base class.
June 13, 2016 at 6:28 pm #1097Just to clarify, we’re talking about what happens when a constructor (and only a constructor) calls an overridden (ie: virtual) method.
The mx2 behaviour might yet change before V1.0, but in general it’s not a good idea for a constrcutor to call an overridden method. I think this sums it up best:
https://msdn.microsoft.com/en-us/library/ms182331.aspx
June 14, 2016 at 6:24 am #1098Looking back at it now, I’m all for it. I see the possible negative consequences of the old way of doing it.
 - 
		AuthorPosts
 
You must be logged in to reply to this topic.