Overloading New() and calling 'upper' New()

Monkey Forums/Monkey Programming/Overloading New() and calling 'upper' New()

V. Lehtinen(Posted 2014) [#1]
Hi!

I'm semi-new to MonkeyX, and what I'm trying to do, is pretty simple:
Class MyClass
    Field x:Float, y:Float, z:Float

    Method New()
        Self.x = 0.0 ' Defaults
        Self.y = 0.0
        Self.z = 255.0
    End

    Method New(x:Float, y:Float)
        New MyClass() ' This cannot be assigned to Self
        Self.x = x ' Only changes X and Y, Z comes from "upper" New()
        Self.y = y
    End
End

Function Main:Int()
    
    Local mc:= New MyClass(10, 20)
    
    Print mc.x ' Prints 10
    Print mc.y ' Prints 20
    Print mc.z ' Prints 0, not 255
End



Any ideas how this is done properly?


dawlane(Posted 2014) [#2]
Method New(x:Float, y:Float)
        New MyClass() ' This cannot be assigned to Self
        Self.x = x ' Only changes X and Y, Z comes from "upper" New()
        Self.y = y
End
This will never work as you are creating a new instance of MyClass with the constructor New() inside the constructor New(x:Float, y:Float). So the instance created by New(x:Float, y:Float) can not see the instance created by New(), unless you make it visible. You could also be creating a memory leak doing it this way, unless the instance goes out of scope when New(x:Float, y:Float) is finished and is cleaned up by the Garbage Collector.

The code below is pointless, as you still have to assign z with what ever was created in the local c. This adds additional over head by creating the c:MyClass instance.
Method New(x:Float, y:Float)
        Local c:MyClass = New MyClass()
        Self.x = x 
        Self.y = y
	Self.z = c.z
End
If you want to assign a default value at instance initialisation. Then write the constructor like this
Method New(x:Float, y:Float, z:Float = 255.0)
        Self.x = x
        Self.y = y
	Self.z = z
End
You can still write the calling method as
Local mc:= New MyClass(10,10)
or is you want to assign another value to z
Local mc:= New MyClass(10,10,128)
Or you can have the Fields written as
Field x:Float, y:Float, z:Float = 255.0
and not bother with Self.z = 255.0 in the constructors at all.
Edit: If I remember, when you created an instance all Fields are automatically assigned default values depending on object type e.g. Int = 0, class:MyClass = NULL


therevills(Posted 2014) [#3]
I would do it something like this:

Strict

Class MyClass
	Field x:Float = 0, y:Float = 0, z:Float = 255 ' assign defaults

	Method New()
		Init(0, 0, 255)
	End

	Method New(x:Float, y:Float)
		Init(x, y, z)
	End
	
	Method Init:Void(x:Float, y:Float, z:Float)
		Self.x = x
		Self.y = y
		Self.z = z
	End
End

Function Main:Int()
	Local mc:= New MyClass(10, 20)
    
	Print mc.x 
	Print mc.y 
	Print mc.z 	
	Return True
End


In Java, you can call the other contructor with "this" - I'm actually surprised that we can't do something similar in Monkey.

public class HelloWorld{
     public static void main(String []args){
        MyClass mc = new MyClass(10.0f,20.0f);
        System.out.println(mc.x);
        System.out.println(mc.y);
        System.out.println(mc.z);
     }
}

class MyClass{
    float x;
    float y;
    float z;
    
    MyClass() {
        x = 0.0f;
        y = 0.0f;
        z = 255.0f;
    }
    
    MyClass(Float x,Float y)
    {
        this();
        this.x = x;
        this.y = y;
    }
}



dawlane(Posted 2014) [#4]
In Java, you can call the other constructor with "this" - I'm actually surprised that we can't do something similar in Monkey.
Would be something nice to have.


V. Lehtinen(Posted 2014) [#5]
In Java, you can call the other contructor with "this"


And that's exactly what I was going for. Guess I'll have to settle with the additional "Init()" method for now... :(

EDIT: Although this could be done by extending the class, then calling Super() to get defaults, but it sounds kinda stupid, doesn't it?


tiresius(Posted 2014) [#6]
In therevils example why is the default New() method not being called inside a "new" object with initialized variables already (i.e. z:Float = 255) ?
In other words, why do we need the Init() method in New() ?


Gerry Quinn(Posted 2014) [#7]
You are right, Tiresius, He probably just forgot he had set a default.


tiresius(Posted 2014) [#8]
Okay thanks I thought I was misunderstanding some quirk of Monkey. :-)


ImmutableOctet(SKNG)(Posted 2014) [#9]
Usually I just have a 'Construct' method where my other constructors are. And, in the case of more advanced hierarchies, I have every class call their super-class's implementation of 'New', and in the ultimate super-class's 'New' command, I have it call 'Construct'. From there, each implementation of 'Construct' uses the "call the super" method, just as 'New' did. The only difference is, 'Construct' provides default values for variables, or sets up variables that always need to be setup. And for anything based on the arguments passed to 'New', I set them up in that implementation, or I make a class-specific construction command which isn't called 'Construct'. This whole thing would be a bit more streamlined if Mark would just allow me to overload methods properly, or at the very least let me call the main 'New' command. I suppose there is setting defaults "in-line", but that still seems terrible to me (For fields at least). But then again, some languages are starting to go this route these days.