function and methods

BlitzMax Forums/BlitzMax Programming/function and methods

zambani(Posted 2009) [#1]
Hi everyone,

Is there any other reason to use a function instead of a method inside a Type besides creating an instance of the Type?

Thanks


H&K(Posted 2009) [#2]
When the function is going to work with ALL or NO, instances of the type.
That is. it functions idependent of any instance


Warpy(Posted 2009) [#3]
defining a Function inside a type is just a way of associating that function with that type, and saving namespace.

For example:
Function finddude(name$)
	For d:dude=EachIn dudes
		If d.name=name Return d
	Next
End Function

Global dudes:TList
Type dude
	Field name$
End Type


is functionally the same as:
Global dudes:TList
Type dude
	Field name$
	
	Function find(name$)
		For d:dude=EachIn dudes
			If d.name=name Return d
		Next
	End Function
End Type


but now you can have lots of types each with a Find function, instead of making finddude, finddog, findtree etc.


Now, methods are fucntions that deal with a particular instance of a type, and allow you access to the instance's fields in the top namespace.

Function changedudename(d:dude,newname$)
	d.name=newname
End Function

Type dude
	Field name$
End Type


is the same as:
Type dude
	Field name$
	
	Method changename(newname$)
		name=newname
	End Method
End Type


but you don't have to pass in the dude you're using as a parameter, and you can write just 'name' instead of 'd.name'.


zambani(Posted 2009) [#4]
Thanks for the responses,
but it seems that there is no reason of using a function over a method at all. A function inside a type can access global vars but never field vars unless the instance is known. However a method inside a type can access field vars and if you specify the name of the type, it can also access global vars within its type.

They both can be used to save namespace, so why not just use only methods and save the function for creating instances only?

Do I have this all wrong?

Thanks.


ziggy(Posted 2009) [#5]
Well, there are several scenarios where a function is a must. As instance, constructors.
How could you cleanly make this, without a function?
Type MyClass
    Field Name:String
    Field PosX:int
    Field PosY:Int
    Function Create:MyClass(Name:String, PosX:int, Posy:Int)
        Local MC:MyClass = New MyClass
        Mc.Name = Name
        Mc.PosX = PosX
        Mc.PosY = PosY
        Return Mc
    End Function
End Type

Local MyVar:MyClass = MyClass.Create("Hello World", 100, 200)

You could create a method creator, but IMHO that sucks. I hate those code using:
MyVar = New MyClass.Create(...
It is not elegant, the constructor is suposed to construct the instance, not tweak it!


Warpy(Posted 2009) [#6]
Or, for another example, my find function shouldn't be a method because it doesn't deal with a specific object.


zambani(Posted 2009) [#7]
@ziggy
What are some other situations besides instance constructor?

@Warpy
What's the downside of using a method for your find function besides "design style"

I hope I'm not asking too many questions :-)
Thanks


ziggy(Posted 2009) [#8]
@zambani: In the very good warpy example, in case it were at method instead of a function, it would be awful.
You would have to create an object instance to find a speciffic/diferent instance!!??. Also, if there are no instances, you have to create one, to perform the find, and realise there are not any.... It should definitevelly be a function and not a method. otherwise, it would be a very good example of a bad design!

I would suggest you to design exactly in the oposite way you're suggesting, Use functions instead of methods when possible, that is, when you're not going to manipulate a instance of the object. Also,not reference the functions using instance names, but the class name. this is a good maintenance practise.


zambani(Posted 2009) [#9]
@ziggy
Aha! I got it now. Use a function when it's related to the class but not any individual instances.

So for example if a had a gameobject class, is it better to make the render routine a function of the class or a method of the instances?


InvisibleKid(Posted 2009) [#10]
right or wrong i don't know, but basicly how i would do it is:

if i want it to be called from outside the type i use a function, and if i want it to be called from inside the type i use a method.

here is a VERY BASIC example of what i mean



i hope that helps some


zambani(Posted 2009) [#11]
@kingNothing

Thanks for the sample code.
It all makes sense now.


Jesse(Posted 2009) [#12]
Ziggy wrote:

How could you cleanly make this, without a function?


I would do it like this:
Type mypix
	Field posX:Int
	Field posY:Int
End Type

Type MyClass
    Field Name:String
	Field pix:mypix
	
	Method New()
		pix = New mypix
	End Method
	
    Method init(Name:String, PosX:Int, Posy:Int)
        Self.Name = Name
        pix.PosX = PosX
        pix.PosY = PosY
    End Method
End Type

Local MyVar:MyClass = New MyClass
myvar.init("Hello World", 100, 200)
Print myvar.pix.posX

I honestly don't know which is better ziggys way or mine but it seems to me that this way is more consistent with variable declarations. I do it either way depending on how I feel at the time of coding but I try to be consistent with a specific code. the "new" constructor also let me initialize types that are included as fields this way I don't forget to initialize any variable types. and the new constructor doesn't have to have anything in it and it will still work.


ziggy(Posted 2009) [#13]
@Jesse: Yes but I was talking about constructors :D


plash(Posted 2009) [#14]
I prefer to do it like this (nice because you can also use it again on an object after it has been created):
SuperStrict

Framework brl.blitz

Type TMyType
	
	Field Something:String, SomethingElse:Int
	
		Method Create:TMyType(_Something:String, _SomethingElse:Int)
			
			Something = _Something ' (Or set method)
			SomethingElse = _SomethingElse ' (Or set method)
			
			Return Self
			
		End Method
		
End Type

Local myobject:TMyType

myobject = New TMyType.Create("Hello World!", 7)

' Later on, if needed, instead of setting variables or recreating the object, we can do this
myobject.Create("Goodbye World!", -1)

(essentially the same as Jesse's Init method, but using Create is more descriptive and you do a one line call - since the Create method returns itself)


Jesse(Posted 2009) [#15]
I don't know Ziggy, I guess I am missing the whole point.


Czar Flavius(Posted 2009) [#16]
You can do this, in case you didn't know

Type MyClass
    Field Name:String
	Field pix:mypix = New mypix



ziggy(Posted 2009) [#17]
@Plash: I understand your point, but in this case, wouldn't it be better to do something like this?
SuperStrict

Framework brl.blitz

Type TMyType
	
	Field Something:String, SomethingElse:Int
		Function Create:TMyType(Something:String, SomethingElse:Int)
			Local MT:TMyType = New TMyType
			MT.SetValues(Something,SomethingElse)
			Return MT
		End Function
		Method SetValues(_Something:String, _SomethingElse:Int)
			
			Something = _Something ' (Or set method)
			SomethingElse = _SomethingElse ' (Or set method)
			
		End Method
		
End Type

Local myobject:TMyType

myobject = TMyType.Create("Hello World!", 7)

' Later on, if needed, instead of setting variables or recreating the object, we can do this
myobject.SetValues("Goodbye World!", -1)

From my point of view, this is a better aproach as the constructor is a constructor, and the value init method is a method. I mean, everything is what it is suposed to be. Just my two cents :D


Jesse(Posted 2009) [#18]
@Czer Flavious
yes, I knew it but the only difference is that with the new method you don't have to create a function to create an instance. You can do it like this:
Type mytype
   Field x:int
   Field y:int
   Field name:String

   Method New()
   End Method
   
end type

local my:mytype = New mytype
my.x = 3
my.y = 10

the new contructor take care of creating the instance. I agree with Ziggy that his way is more convenient and easier to understand and probably the right way. I will respect his opinion as he is the most experienced but I can't help thinking that logically my way is more correct although I am not experienced inough to make that assumption.


N(Posted 2009) [#19]
While we're on the init bandwagon:

Type TTypeName
	Field _a:Int, _b:Int, _c:Int
	
	Method Init:TTypeName( a:Int, b:Int, c:Int )
		_a = a
		_b = b
		_c = c
		Return Self
	End Method
End Type

Local obj:TTypeName = New TTypeName.Init( 10, 20, 30 )



H&K(Posted 2009) [#20]
They both can be used to save namespace, so why not just use only methods and save the function for creating instances only?

As well as constuctors, and more inportantly, Functions dont need ANY instance of the type.

So, prep work for the type,
Changing GLobals of the type. etc

ALso, as said, working on the WHOLE type

So, counting thro the types list
Freeing all instances of the type
Adding all the values of some field togther etc


Muttley(Posted 2009) [#21]
I personally prefer:
Type TTypeName

   Field a:Int
   Field b:Int
   Field c:Int
	
   Method Init:TTypeName(a:Int, b:Int, c:Int)
      Self.a = a
      Self.b = b
      Self.c = c
   End Method
	
End Type

Local obj:TTypeName = New TTypeName
obj.Init(10, 20, 30)



Arowx(Posted 2009) [#22]
I go with Ziggy's style, calling a one line create funciton on the Type is easier, and as all it does is use an init/setup method to set the varibales you get the best of both worlds...

One line creation
Optional reuse/reset via init/setup methods

And it's the way I've been doing it for a while, still it would be nice to be able to setup a default constructor e.g.

Local obj:TType = New TType(x,y,z)


Brucey(Posted 2009) [#23]
calling a one line create funciton on the Type is easier

One issue with this is that it is difficult to use it on an extended object using a shared "create".

For example :

Type A
    Method Create:A()
        ' do stuff
    End Method
End Type

Type B Extends A

End Type

Here, you can do :

Local obj:B = B(New B.Create())

Rather than having to implement a new Create() function for each subclass, which is what you would have to do using a Function.

I've tended to use both the Function and Method creates in my wxMax implementation. If you want to extend a built-in widget, you must use the method I mention above. Otherwise, you could use the Function or Method to create the instance of the Type.

Implementation looks like this :

where a subclassed button ...

Type MyButton Extends wxButton

...could be created using a call such as :

Local button:wxButton = new MyButton.Create(......)

Keeps things flexible and easy to read.


Arowx(Posted 2009) [#24]
Nice point Brucey, it's something I have noticed but I'm that used to writing a Create function with each class it's amost automatic now!

Would therebe any possibility to have a constructor added to the language to get around these workarounds?