Best way to access information inside classes?

Monkey Forums/Monkey Programming/Best way to access information inside classes?

Redbeer(Posted 2013) [#1]
The code I have below uses three different processes to accomplish the same thing.

The first passes the entire objects into a Function, the second passes the object fields separately, the third uses a method inside the class and passes the fields in individually.

I can also envision a process where I create properties/getters and setters to access the information.

My question is, which is the better way to do it?

I would imagine that as a function, passing in the fields individually makes the function more generic, because it isn't dependent on my custom GameObject type, but I'm unsure what other considerations are important.

My concerns are:
1) If I want to not only access the information, but also potentially modify the values of any given field inside an object, using a function or method, which is the best approach?
2) Which is easier on memory, passing the whole object in each frame or passing in parameters separately, or accessing each field as a property?
3) If I create an arraylist of objects, how does that change the approach, pass each object, pass each field, or get/set each field from within the function or method?
3) What am I missing in terms of considerations?


Strict

Import mojo


Class MyGame Extends App
	Field gameObject1:GameObject
	Field gameObject2:GameObject
	Field flag:Int
	Field flag2:Int
	Field flag3:Int
	Field direction1:Float=1
	Field direction2:Float=1
	'This contains our application as a whole, including game and title screens and any others we create.
	Method OnCreate:Int()
		SetUpdateRate(60)
		gameObject1 = New GameObject(10, 10, 20, 20)
		gameObject2 = New GameObject(35, 30, 20, 20)
		Return 0
	End
	
	Method OnUpdate:Int()
		gameObject1.xPos = gameObject1.xPos + 2*direction1
		gameObject2.xPos = gameObject2.xPos + 1*direction2
		flag = CheckCollision(gameObject1, gameObject2)
		flag2 = CheckCollision2(gameObject1.xPos, gameObject1.yPos, gameObject1.width, gameObject1.height, gameObject2.xPos, gameObject2.yPos, gameObject2.width, gameObject2.height)
		flag3 = gameObject1.CheckCollision3(gameObject2.xPos, gameObject2.yPos, gameObject2.width, gameObject2.height)
		If gameObject1.xPos + gameObject1.width >= DeviceWidth()
			direction1 = -1
		End
		If gameObject1.xPos <= 0
			direction1 = 1
		End
		If gameObject2.xPos + gameObject2.width >= DeviceWidth()
			direction2 = -1
		End
		If gameObject2.xPos <= 0
			direction2 = 1
		End	
		Return 0
	End
	
	Method OnRender:Int()
		Cls(0,0,0)
		gameObject1.Draw
		gameObject2.Draw
		DrawText(flag, DeviceWidth()/2, DeviceHeight()/2)
		DrawText(flag2, DeviceWidth()/2, DeviceHeight()/2 + 12)
		DrawText(flag3, DeviceWidth()/2, DeviceHeight()/2 + 24)
		Return 0
	End
End

Class GameObject
	Field xPos:Float
	Field yPos:Float
	Field width:Float
	Field height:Float
	
	Method New(x:Float, y:Float, w:Float, h:Float)
		Self.xPos = x
		Self.yPos = y
		Self.width = w
		Self.height = h
	End
	
	Method Draw:Void()
		SetColor(0, 255, 0)
		DrawRect(Self.xPos, Self.yPos, Self.width, Self.height)
	End
	
	Method CheckCollision3:Int(x2:Float, y2:Float, w2:Float, h2:Float)
		If Self.xPos > (x2 + w2) Or (Self.xPos + Self.width) < x2
			Return 0
		End
		If Self.yPos > (y2 + h2) Or (Self.yPos + Self.height) < y2
			Return 0
		End
			Return 1
	End
End

Function CheckCollision:Int(object1:GameObject, object2:GameObject)
	If object1.xPos > (object2.xPos + object2.width) Or (object1.xPos + object1.width) < object2.xPos
		Return 0
	End
	If object1.yPos > (object2.yPos + object2.height) Or (object1.yPos + object1.height) < object2.yPos
		Return 0
	End
		Return 1
End
	
Function CheckCollision2:Int(x1:Float, y1:Float, w1:Float, h1:Float, x2:Float, y2:Float, w2:Float, h2:Float)
	If x1 > (x2 + w2) Or (x1 + w1) < x2
		Return 0
	End
	If y1 > (y2 + h2) Or (y1 + h1) < y2
		Return 0
	End
		Return 1
End

Function Main:Int()
        New MyGame
        Return 0
End



Redbeer(Posted 2013) [#2]
So no one has any input on this?

Maybe if I frame the question differently.

Why choose a function vs. a method?

After that choice, why choose to pass individual parameters vs. passing whole objects vs. accessing information with properties or getters/setters?


Gerry Quinn(Posted 2013) [#3]
To some extent, if you don't know the answer, the question doesn't matter here. Because in every case you are doing the same thing. The only issue is what will give you code that looks nice, has fewer bugs, is easier to extend etc.

For example, you *can* use object methods and properties to hide the internal implementation of xPos and yPos. But whether that really gains you anything depends on how likely the implementation is to change.

I prefer the first version of CheckCollision because it is easier to read, and it does not affect the objects that are passed as parameters.

You could make similar functions called Move( object:Object ) and Bounce( object:Object ) to cover what you do in OnUpdate() - but in this case you must note that Bounce() affects the object parameters. I would usually prefer to call such functions rather than dump everything in Update() [my bananas example notwithstanding].

The thing with object orientation is that trying to find the perfect system is a waste of time. Find a reasonably decent and fairly consistent way of doing things. With more experience it will come easier as you will be coding with a better eye as to what you will be doing later.


Nicholas Peanut(Posted 2013) [#4]
"My question is, which is the better way to do it?"

-it depends and also doesn't matter that much for now.

"Why choose a function vs. a method?"

functions are static while methods need an instance.
I would imagine functions are faster because of that.
but generally instance methods are more OOP and look cleaner (to me atleast)


" pass individual parameters vs. passing whole objects vs. accessing information with properties"
again this depends on personal taste etc. but I like my api to be clean and small, so if your code would test if two gameobjects overlap it makes sense to pass in two gameobjects. (opposed to 8 parameters)

or pass in one gameobject to an instance method.
like
Method IsCollidingWith(other:GameObject)

on the other hand your code seems to test if two rectangles overlap so a static function (in some utility class) like

Function RectsOverlap(rect1:Rectangle, rect2:Rectangle)
would seem logical too.


Redbeer(Posted 2013) [#5]
Thanks a lot for the replies.

I understand that the answer varies, most answers do, but I was just sort of looking for some rules or thumb that may or may not contradict my own.

Here's how I typically rationalize these choices:
When I use methods:
If what I need to do only uses or modifies the information for the object itself, I typically make a method to do it, so the functionality is with the data. I use this rule even if there is some necessary external "trigger" that needs to go off to make this happen.

When I use functions:
If the process needs to do one particular thing, but needs to do that thing to many of the same or different objects, I typically use a function.

Whether I pass parameters, or objects, or use properties:
If what I need to do is generic enough, and there are a limited number of properties, I use individual properties that are type int, float, etc. I do this so I can reuse the function as much as possible with different things. If the function/method needs to take in lots of data, and that data is specific to the type of object(s), then I pass objects in.

I don't typically find use for properties, or getters and setters, but maybe that is because I work alone? While I can see how they work, I'm curious what the primary reason for using those are.

The main issue is that while I've written lots of code over the years, I'm an engineer, not a computer scientists/programmer by training. So I'm pretty good at solving problems, and can get almost anything to work, and even work well, but I have no idea what the "best approach" is. Therefore, even though I'm successful, I'm curious whether or not my practices are sound, in general.

Any other feedback people can provide would be appreciated.


Difference(Posted 2013) [#6]
Just watched this video yesterday, and there are a few thoughts on this half an hour in : 30:09

https://www.youtube.com/watch?feature=player_embedded&v=c-kav7Tf834