function and methods
BlitzMax Forums/BlitzMax Programming/function and methods
| ||
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 |
| ||
When the function is going to work with ALL or NO, instances of the type. That is. it functions idependent of any instance |
| ||
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'. |
| ||
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. |
| ||
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! |
| ||
Or, for another example, my find function shouldn't be a method because it doesn't deal with a specific object. |
| ||
@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 |
| ||
@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. |
| ||
@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? |
| ||
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 |
| ||
@kingNothing Thanks for the sample code. It all makes sense now. |
| ||
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. |
| ||
@Jesse: Yes but I was talking about constructors :D |
| ||
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) |
| ||
I don't know Ziggy, I guess I am missing the whole point. |
| ||
You can do this, in case you didn't knowType MyClass Field Name:String Field pix:mypix = New mypix |
| ||
@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 |
| ||
@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. |
| ||
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 ) |
| ||
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 |
| ||
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) |
| ||
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) |
| ||
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. |
| ||
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? |