monkey features that blitzmax doesnt have

Monkey Forums/Monkey Programming/monkey features that blitzmax doesnt have

slenkar(Posted 2011) [#1]
what language features does monkey have that blitzmax doesnt?


Tibit(Posted 2011) [#2]
Monkey has Generics, imo a neater module-file-import-system, constructors, and (my favourite) Properties. Support for Private and Public.

Properties is probably the thing that made the biggest difference to the way I code in Monkey compared to Blitzmax.


Shinkiro1(Posted 2011) [#3]
I asked this in another thread already but what exactly are properties and what advantage do they have over normal getter methods? Is the compiler doing some special magic to optimize these methods?

On topic: The things Tibit mentioned + function overloading + the fact a Type is now called a Class ^^


slenkar(Posted 2011) [#4]
hmm i would like to know more about properties too, (and generics)


Tibit(Posted 2011) [#5]
Right, overloading of course.

Well sure, here is my rundown of those topics:

Generics connected to inheritance
To explain generics I'd start with inheritance. You probably know what inheritance is, it is when you have one class A and then you want to make a class B that is exactly the same as A but has some extra stuff, instead of duplicating code we can with the use of Inheritance "Extend" A when we want to write B and we can do this for any class that needs all of A's functionality.

It also has the Polymorphism effect, which is that in a List or a Variable that is of the the Base Class A, can be used to store B's. Since any object of class B is ALSO the Class A.
Class Tree
End

Class OakTree Extends Tree
End

' This is normal
Local myTree:OakTree = new OakTree

'This is polymorfism
Local harvesterTreeContainer:Tree = myTree

'We can then cast it back 
Local droppedOakTree:OakTree = OakTree(harvesterTreeContainer)
This means we can let Classes, like a harvester Class, be built to hold any Tree that inherits from the Class Tree instead of the specific tree-classes. This has a great benefit, that the harvester class does not know about Oak-Trees or any other Tree what we might want to add, it just handles the more abstract concept of Tree, and in this way the harvester does not need to be changed when we add more Tree-Classes.

Now I'm talking only about the actual usage here, however in the real world there are many more aspects to writing good quality code beyond avoiding redundant (duplicated) code.

Likewise there are many aspects to take into consideration before using inheritance or generics beyond just writing the code.

So what is Generics?
Generics is a flexible way of inheritance. It is not something you use every day. The problem the Generics solve is that of casting. Without Generics a list or variable must use a certain Class, like shown below. So I might make a Tree-List that handles Tree's. If I want the list to handle *anything* then that list must contain objects of the Class Object.

It might seem this is only more flexible, since if our harvester above could hold Objects instead of Tree's it could hold anything we can come up with, since every Class automatically Extends the built-in Object Class.

However each time we want to make use of a class in a object-list or a object-variable we must convert it back to an object of the original Class.
' put into a object-box
Local box:Object = droppedOakTree

' Convert back - this gives an compile error...
harvesterTreeContainer = box

' So we need to specifically tell the compiler we know what we are doing and CAST it back:
harvesterTreeContainer = Tree(box)


Casting can reduce code understandability, make code more cluttered, have a slight performance cost, and in can induce errors related to casting. Worst of all I think, is that you get the Cast-Error when you run, not when you compile!

In this case, let's say we know we only want the harvester to handle trees, it's simple we use variables that handle Trees. However assume the case that I have another Harvester that handles Cows, not Trees. And another harvester that handles Crops, not Trees nor Cows. I could make my harvester use objects, casting and lots of type checks. Or I can use Generics.

Generics means I define the Harvester with one or more custom Classes that are of an undefined type, I might call the Class that the Harvester calls for A. Methods in the Harvester can now refer to A, and not until you create a new harvester you define what A is. You can then make A a Tree, a Crop or any other object, however once you have created a Tree-Harvester you cannot put non-tree objects into it, however neither do you ever have to Cast anything, since all methods that handles A, now actually return actual Trees.

Generics is very useful in Collections:

Local treeList:= new List<Tree>

This list holds only Tree-Objects, but when I want to get a Tree from this List, like treeList.First I get a Tree, not an Object, and therefore no casting is necessary.

Making a class Generic is as simple as providing the type (or types) like this:
Class Harvester<T>
    Field Grip:T 
	Method PickUp:Void( objectToPickUp:T )
		Grip = objectToPickUp
		Print "Picked up a thing"
	End
	Method Drop:T()
		Print "Dropped a thing"
		Return Grip
	End
End

'Example Use
Local harvester:= New Harvester<Tree>
harvester.PickUp myTree
harvesterTreeContainer = harvester.Drop


Also note that in this example OakTree is still a Tree, and if our Harvester handles Trees it can also handle Oaks, but if it where to handles OakTrees it could not handle "just" Trees --> you will get a compile error.

More on Properties later on, they are much simpler :)


Shinkiro1(Posted 2011) [#6]
Thanks for this awesome tutorial.

So basically you can define the datatype of fields at runtime and don't have to hardcode it?

I'm looking forward for your next article on properties.

EDIT: I've looked into the monkey module folder and the list gave me some insights. Just wanted to mention.


wiebow(Posted 2011) [#7]
I grasped this from the docs, but it is more clear to me now. Nice write up! Looking forward to the Properties explanation. =]


slenkar(Posted 2011) [#8]
I think I get it,

so if you were making a collection you only have to write the code once, and it returns the proper type e.g. tree

otherwise you would have to write the code for a treelist to make the list return trees.


Tibit(Posted 2011) [#9]
Thanks for the feedback, yea your are all getting it I'm sure, I won't say most programmers will make their own Generic classes every day, but you probably will use others a lot :)

So basically you can define the datatype of fields at runtime and don't have to hardcode it?
Exactly.

Properties
Properties are a very simple concept related to Object Oriented Programming. The idea behind properties is to allow you to keep an Object like a black-box, all input and output and are handled by methods. The benefit with that is that if I change the internal workings of that class without changing the external interface, no external code needs to be rewritten.

This led to some programmers creating get and set methods for many of their variables. Eventually some languages realized that a lot of programmers programmed this way and the concept of Properties was invented.

There is nothing you can do with Properties that you can't do with a normal get and set method. The ONLY difference is that Properties can be cleaner to look at and use. Let's look at the result:
Class SpaceShipGetSet
	Private 
	Field fuel:Int
	
	Public 
	
	Method GetFuel:Int()
		Return fuel
	End
	
	Method SetFuel:Void( amount:Int )
		'Note logic can be added here!
		Print "Fuel Set to "+amount
		fuel = amount
	End
End

Class SpaceShipProperties
	Private 
	Field fuel:Int
	
	Public 
	
	' Since this returns something, but has no parameters, it is a GET Property
	Method Fuel:Int() Property
		'Note that logic can be added here!
		Return fuel
	End
	
	' Since this has 1 parameter, it is a SET Property
	Method Fuel:Void( amount:Int ) Property
		Print "Fuel Set to "+amount
		fuel = amount
	End
End
Function Main:Int()
	Local ship1:SpaceShipGetSet = New SpaceShipGetSet
	ship1.SetFuel 200 
	Print "ship1 Current Fuel: "+ship1.GetFuel

	Local ship2:SpaceShipProperties = New SpaceShipProperties
	ship2.Fuel = 200
	Print "ship2 Current Fuel: "+ship2.Fuel
End


In most cases your properties is going to return values. Before you might have had a method called highScoreList.GetScore() now you can go highScoreList.Score

It is optional if you want to add both a GET and a SET, or if you only want to add ONE of them. Some times you might want to have a GET Property, like Score, that returns something that is calculated.

However this does not mean you should make all your methods will one parameter or one result a Property, try to use properties whenever you GET or SET a value, but not when you do more advanced calculations in the background. A main rule is often that a SET, GET always set or return the same result when called multiple times in a row.

It is expected that

Print ship.Fuel
Print ship.Fuel
Print ship.Fuel

Prints the same value 3x times.

Properties allow you to design an interface to your class that looks like direct data access, while still keeping encapsulation possibility on that field.

It is quite common with properties that have a public GET, and a private SET. You can also use properties with inheritance.


Tibit(Posted 2011) [#10]
Overloading is used when you have one method that does one thing, but that can be called using different parameters.

Here is an example using the New() constructor that I commonly use:
Class Tank
	Method New()
		' Use default position
	End 
	
	Method New( x:Int, y:Int )
		' specify start-x and y
	End 
	
	Method New( position:Vector )
		' use a vector to show start-position
	End 
End
I can now go:

new Tank

or

new Tank 345, 100

or

new Tank Factory.ExitDoor.Position

Can be Handy!

However I only use it when the input parameter means the same thing, and when the overloaded methods or functions all does the same thing.


Warpy(Posted 2011) [#11]
I didn't know about properties! Gosh.


dopeyrulz(Posted 2011) [#12]
Properties are great because they allow you expose only what you want. For example you might have an Id field which you don't want changed once its been set (read-only). You would set it via the New constructor and only have the get property for Id:

Class MyObject
Private
   Field _id:String
Public

   Method New(id:String)
      _id = id
   End

   Method Id:String() Property
      Return _id
   End

End Class


The other benefit as Tibit pointed out in his example is adding validation to the Set property to ensure the value is valid. You could also call some sort of routine from it as well. Properties are very common in .Net and work well.