Get and Set in the same method?

BlitzMax Forums/BlitzMax Beginners Area/Get and Set in the same method?

Gabriel(Posted 2005) [#1]
I'm probably overlooking something simple, but here we go anyway. How can I have a method which allows me to both set and get a field ( or several fields ) of a type.

For example :

Type Ship
   Field XPos:Int,YPos:Int

   Method X() ' WHAT HERE?
      ' WHAT HERE?
   End Method

End Type

Local MyShip:Ship=New Ship
MyShip.X(4)
Print MyShip.X()


I thought of using a default null integer for the parameter of the X Method, but since a null integer is equal to zero, that means I can't set the X Position to zero, so no go there.

And before some bright spark says "forget the method, you only need to set or get the field", I know that, this is just a simple example. In the actual code, it won't actually be a field and I need to be able to both get and set with methods. Worse case, I can use two different methods, but it would be nice not to have to.


WendellM(Posted 2005) [#2]
Something like this maybe?
Type Ship
	Field XPos:Int, YPos:Int

	Method DoIt( Action$, X Var, Y Var )
		Select Lower( Action )
			Case "set"
				XPos = X
				YPos = Y
			Case "get"
				X = XPos
				Y = YPos
		End Select
	End Method

End Type

Local MyShip:Ship=New Ship
Local X, Y
X = 4
Y = 7
MyShip.DoIt( "set", X, Y )

Local MyOtherShip:Ship=New Ship
MyOtherShip.DoIt( "get", X, Y )
Print X
Print Y

MyShip.DoIt( "get", X, Y )
Print X
Print Y



HappyCat(Posted 2005) [#3]
What about something like:

Const NullInt:Int = -2147483648

Type Ship

   Field XPos:Int,YPos:Int

   Method X:Int(Value:Int = NullInt)
		If Value <> NullInt
			XPos = Value
		End If
		Return XPos
   End Method

End Type

Local MyShip:Ship=New Ship
MyShip.X(4)
Print MyShip.X()


I think it's pretty unlikely that you'll want to legitimately set a property to -2147483648.

You could also do something similar for most other datatypes:

Const NullString:String = "SomeGarbageThatYou'llNeverActuallySetAStringTo"
Const NullLong:Long = -9223372036854775808
Const NullFloat:Float = whatever the min value is for float
etc.

And put these all in a common file that you include wherever needed.

Can't see it working well for unsigned datatypes though (Short, Byte etc).


Bremer(Posted 2005) [#4]
Type Ship
   Field XPos:Int,YPos:Int

   Method X(XPos:int=-9999)
	if XPos = -9999 then return self.XPos
	self.XPos = XPos
   End Method

End Type


Its untested, but I was thinking that you would call it like this:
X = MyShip.X() ' get X
MyShip.X( 100 ) ' set X

[edit] looks like I was a little slow and HappyCat have already suggested something similar. I think it would work just fine.


Who was John Galt?(Posted 2005) [#5]
Why not have separate set and get methods? I don't see any advantage in combining them.


Gabriel(Posted 2005) [#6]
Thanks for the suggestions, guys. I think I'm going to go with Wendell's version, as I will have no control of the fields' contents. Therefore there is no way for me to prevent the field legitimately needing to be -9999, -9223372036854775808 or whatever else.

Of course, if Null did what the documentation suggests it does, it would be ok. But despite the docs describing Null as a constant for an empty object instance, that only applies to custom types, it seems, not the inbuilt data types. I guess I can always make a feature request for that. Won't get it, but I can ask.

Why not have separate set and get methods? I don't see any advantage in combining them.


No particular reason other than it's cleaner when you're writing reusable code to have half the number of methods. A lot of libraries allow you to do this, and I like it.


Jay Kyburz(Posted 2005) [#7]
I do like this idea. I've started writing setters for all of my fields as standard but haven't yet come across a need for getters.

I know it theory why you have them but can you guys give me any examples of how you use them?

Shame you can do this

Method X:Int(Value:Int = self.x)


Perturbatio(Posted 2005) [#8]
Use null instead of setting a specific value (null can be interpreted as an int)
Type test
	Field _X:Int = 10
	
	Method X:Int(val:Int=Null)
	
		If Not val=Null Then
			_X = val
		EndIf
		
		Return _X
		
	End Method
End Type

Local t:test =  New test
Print t.x()
Print t.x(100)



Jay Kyburz(Posted 2005) [#9]
yeah.. but its interpreted as 0 so you can never set the value to 0.


Perturbatio(Posted 2005) [#10]
yeah, fair enough, I'll let you off this once ;)


Sarge(Posted 2005) [#11]
How about something like this ?

Type Ship

	Field XVal:Int

	Method X:String( Value:String )
		 
		If Value = "get" Then
			Return Self.XVal
			Else
			Self.XVal = Value.ToInt()
		End If
	
	End Method

End Type

Test:Ship = New Ship

Test.X( 50 )
Print Test.X( "get" )



Jay Kyburz(Posted 2005) [#12]
I've been thinking about this today and I'm not sure I want methods with the same name as my fields where the only thing distinguishing them is a set of brackets. I'm not very disciplined when really powering through an idea and I think I'd forget them all the time (leading to hard to find bugs)

I'll stick with SetX. (and possibly GetX if I can think of a good reason to implement Getters)

When the new IDE is released I'd like to implement auto creation of these methods.


Sarge(Posted 2005) [#13]
Please tell me if i missed something with the Null Pointer, why does this set/return 0 :
Type Ship

	Field XVal:Int
	
	Method X:Int( Value:Int = Null )
		 
		If Value = Null Then
			'If you think it wont set it to 0 then just add,
			'Value = 0
			Return Self.XVal
			Else
			Self.XVal = Value
		End If
	
	End Method

End Type

Graphics 800,600, 0

Test:Ship = New Ship

Test.X( 0 )
Print Test.X()

While Not KeyHit( key_escape )
Cls
	
	DrawRect( Test.X(), 50, 100, 100 )

Flip
Wend



Who was John Galt?(Posted 2005) [#14]
Beacuase Null is like a constant of 0 for ints.