Return Self - What does that do?

Monkey Forums/Monkey Beginners/Return Self - What does that do?

Pakz(Posted 2015) [#1]
I am reading through code on this forum and I saw in a Class that you can Return the Self command. What does this do and how can you use this?

Looking at the code it does not seem to do anything as far as I can tell.

The code was here in this thread : click me

edit :

After some reading I think it creates a new instance of the class right?


therevills(Posted 2015) [#2]
Self is the current object (it does not create a new instance), when a method returns "self" you can chain commands up pretty nicely.

So let's take a cut down version of the Vector class:
Class Vector
	Field x:Float
	Field y:Float
	
	Method New(x:Float,y:Float)
		Self.x = x
		Self.y = y
	End

	Method Add:Vector(x:Float,y:Float)
		Self.x += x
		Self.y += y
		Return Self
	End
End


Using the method Add, you can return the current object and also chain methods together:
Strict

Function Main:Int()
	Print ("Start!")
	Local v:Vector = New Vector(100, 100)
	Print v.ToString()
	
	Local anotherVector:Vector = v.Add(10, 10)
	Print v.ToString()
	Print "Another " + anotherVector.ToString()
	' chain
	v.Add(10, 10).Add(20, 20).Add(10, 10)
	Print v.ToString()
	Return True
End

Class Vector
	Field x:Float
	Field y:Float
	
	Method New(x:Float,y:Float)
		Self.x = x
		Self.y = y
	End

	Method Add:Vector(x:Float,y:Float)
		Self.x += x
		Self.y += y
		Return Self
	End
	
	Method ToString:String()
		Local rv:String
		rv = "Vector x = " + Self.x + ", y = " + Self.y
		Return rv
	End
End


This outputs:
Start!
Vector x = 100, y = 100
Vector x = 110, y = 110
Another Vector x = 110, y = 110
Vector x = 150, y = 150



Pakz(Posted 2015) [#3]
But what is chaining for then? I am confused on what can be done with it. It just seems to be calling a function 3 times in one line? Is there any technique in game programming that makes this useful? For bullets or ai or so?


Samah(Posted 2015) [#4]
It makes your code a million times cleaner and removes the requirement for temporary variables.


therevills(Posted 2015) [#5]
Its just syntactic sugar.

For your bullet example you could do something like this:

Local b:Bullet = New Bullet
b.SetColor(RED).SetSpeed(10).SetAngle(45).SetPower(100)



Pakz(Posted 2015) [#6]
I understand now. I was able to make something myself and I got it working :)


This is what I made.




Samah(Posted 2015) [#7]
Perfect! ;)


bitJericho(Posted 2015) [#8]
I would be careful with method chaining it can make things really confused. Where I have used something similar to this though is when dealing with parent/child relationships between the same or different classes. For example:

Strict

Class Parent
	Field name:String

	Method New()
		Self.name = "mom"
	End
End

Class Child
	Field parent:Parent

	Method New(parent:Parent)
		Self.parent = parent
	End

End

Function Main:Int ()
	Local mom:= New Parent()
	Local daughter:= New Child(mom)
	    
	Print daughter.parent.name
	
	Return 0
End


Second example:

Strict

Class Person
	Field name:String
	Field parent:Person

	Method New(parent:Person, name:String)
		Self.name = name
		Self.parent = parent
	End
End

Function Main:Int ()
	Local mom:= New Person(Null,"mom")
	Local daughter:= New Person(mom,"daughter")
	    
	Print daughter.name
	Print daughter.parent.name
	
	Return 0
End



therevills(Posted 2015) [#9]
That's not method chaining, you are just accessing variables directly.

But yes I do agree that you do have to be careful with method chaining, some people do also call it "train wreck " (due to having methods one after another)...


Samah(Posted 2015) [#10]
@therevils: ...some people do also call it "train wreck "...

It's only a train wreck if there are no periods or parentheses and all the words are squished up. Otherwise it's just a train. ;)


bitJericho(Posted 2015) [#11]
That's not method chaining, you are just accessing variables directly.


I realize that, it's just kind of in a similar (and imo more useful) vein. It's similar cuz you can do things like: gen1.gen2.gen3.cousin.parent(lookup).name. For example I took advantage of this in an XML parser, I think it's a lot cleaner than using method chaining, which can also be used really effectively with xml parsing. Anyway, choose the right tool for the job :)


Gerry Quinn(Posted 2015) [#12]
Strictly speaking, 'Return Self' is what a constructor (the New method) does. It's just that the type and return are implicit.


Samah(Posted 2015) [#13]
@bitJericho: I realize that, it's just kind of in a similar (and imo more useful) vein.

It's not really similar at all. Method chaining is intended for a single class (it gets messy if you try to do it with inheritance), whereas you're talking about inherited fields.

@Gerry Quinn: Strictly speaking, 'Return Self' is what a constructor (the New method) does.

Kind of, but you need to keep in mind that constructors will always "Return Self", and can never "Return Null" as a method may do. This means that you should never do a Null check on a variable immediately after assigning it a new object. It is guaranteed to have a reference to a new object, unless an exception is thrown.