OK, so I still don't get properties!

Monkey Archive Forums/Monkey Discussion/OK, so I still don't get properties!

DruggedBunny(Posted 2011) [#1]
I noticed Samah's recent post about properties, and that reminded me that I'd never quite grasped what they did differently to a plain method. A quick search turns up an example, also from Samah, which looks like this:

Class Foo
Private
  Field bar:String

Public
  Method Bar:String() Property
    Return bar
  End

  Method Bar:Void(bar:String) Property
    Self.bar = bar
  End
End

Function Main:Int()
  Local f:Foo = New Foo
  f.Bar = "Hello World!"
  Print f.Bar
  Return 0
End


I get what this does, and I get the practise of providing a particular way of accessing fields, but what I don't get is why the above is different to this:


Class Foo
Private
  Field bar:String

Public
  Method Bar:String()
    Return bar
  End

  Method Bar:Void(bar:String)
    Self.bar = bar
  End
End

Function Main:Int()
  Local f:Foo = New Foo
  f.Bar = "Hello World!"
  Print f.Bar
  Return 0
End


(I've simply removed the keyword Property.)

I simply haven't managed to pick up on what Property actually does!

Lastly, and mostly off-my-own-topic, while trying to figure it out, I unexpectedly found I could do this -- surely a bug?


Class Test

	Method Whatever (anything:String)
		Print anything
	End
	
End

Function Main ()

	Local t:Test = New Test
	t.Whatever "Hello"
	t.Whatever = "Hello"        ' WTF?!
	
End


Oh, and another thing! Running Samah's original example in STDCPP gives two warnings, though it still works:


main.cpp: In constructor 'bb_untitled1_Foo::bb_untitled1_Foo()':
main.cpp:913:16: warning: attempt to free a non-heap object 'null' [enabled by default]
main.cpp: In function 'int bbMain()':
main.cpp:913:16: warning: attempt to free a non-heap object 'null' [enabled by default]


Is this something that might need to be looked at by Mark?


Jesse(Posted 2011) [#2]
I am not sure I get it completely myself but I think this is how it works:

when you declared the method as a property, the value can be assigned with the equal while the other way it would have to be assigned through the method parenthesis
take your code for example:
 	Method Whatever (anything:String)
		Print anything
	End

for that, you would have to call the method like so:
t.Whatever("Hello")

or
t.Whatever "Hello"


but if you had declared the Method as such:
	Method Whatever (anything:String) Property
		Print anything
	End

you can now call it with the equal:
t.Whatever = "Hello"



note that Samah created two methods one to pass it to the method:
  Method Bar:Void(bar:String) Property
    Self.bar = bar
  End

and one to return from the method:
  Method Bar:String() Property
    Return bar
  End


the second one will have to be created to return a value from the method.
I haven't tested it with Functions but I guess it works the same way.

I guess is a way for method to be represented as a variable.


Samah(Posted 2011) [#3]
Properties are generally used to expose private fields and to let the developer do some magic calculations in the background.

Here's some code inspired by a C# example:



Basically this lets you set the value in hours as if it were a variable, but it actually stores it internally in seconds. Then you can use the other properties to read the value in other formats.

Edit: As for this code working without the Property keyword, I would call that a bug.
f.Bar = "Hello World!"

It should really fail compilation. I also don't like the fact that you can omit parentheses in method calls. To be honest, the Monkey syntax is much too lazy for my tastes. "Optional" syntax promotes lazy coding, in my opinion.


ziggy(Posted 2011) [#4]
As for this code working without the Property keyword, I would call that a bug.

+1 Maybe we should raise a bug report to Mark?


FlameDuck(Posted 2011) [#5]
Another use for properties is pure semantics. When using reflection in Java (which doesn't have properties) there's no way to tell if the get/set method you just found was actually a property or just an unfortunately named method. Anyone who's worked with Java/Spring Beans and EL will tell you this is huge pain in the ass.

In C# (which does have properties), you never get the two mixed.

As for Monkey, it's hard to say what you absolutely *need* them for, apart from using the assignment operator as convenience (and readability), which seems to work regardless.


Gerry Quinn(Posted 2011) [#6]
What's the difference between a property and an 'unfortunately named method'? Aren't they still just get and set methods with different syntax?


DruggedBunny(Posted 2011) [#7]
Thanks all... I'll have to mess around a little and see whether or not it makes much practical difference to me. I have to say, I thought there would be more to properties than this!

I suppose this controlled-access stuff might mean more if you're a professional/serious coder using intellisense to bring up objects' "public" fields/methods as a way of seeing what you have access to without referring to the docs, and stuff like that, assuming such a system would skip the presentation of private fields, etc.


I also don't like the fact that you can omit parentheses in method calls



Yeah, I used this a fair bit early on, but I've reverted to using brackets, at least when returning values from functions/methods.

I'll go post the Method = String thing as a bug. Thanks again.


FlameDuck(Posted 2011) [#8]
What's the difference between a property and an 'unfortunately named method'?
The latter may not be a property (i.e. something which reflects the state of the object).


Tibit(Posted 2011) [#9]
Remember you can inherit Properties and have them in Interfaces :)

And you can do stuff like:

Method On:Bool() Property
return isOn
End

Method Off:Bool() Property
return Not isOn Or list.Length = 0
End

Not that above is a good example, but I just wanted to point out that you can make you logic look more sane sometimes using properties - even tough it just returns a field.

btw I wrote a tutorial on Properties and another on Generics many months back, but I could not find it using search?


DruggedBunny(Posted 2011) [#10]
Method On:Bool() Property
return isOn
End

Method Off:Bool() Property
return Not isOn Or list.Length = 0
End


See, I still don't get the difference, at least compared to this:

Method On:Bool()
return isOn
End

Method Off:Bool()
return Not isOn Or list.Length = 0
End


With Monkey, you don't even have to use brackets for methods, so calling either would look exactly the same (I think!), eg.

If myobject.On Then Print "Hello"


So, all I've gathered about properties is that you can provide the illusion of reading from or writing to a field (albeit in a 'safe' way), but other than the calling syntax, is that the only difference?


ziggy(Posted 2011) [#11]
The usage. A property should represent a status in a class. A method should perform actions. As instance, in a GUI library, the X and Y position of a window can be properties, so when you modify the values, the internal API calls to move the window are called.

Example using properties (x is a property)
myWindow.X+=1


Example not using properties, but using get / set:
myWindow.SetX(myWindow.GetX()+1)


Example using field + method:
myWindow.x+=1
myWindow.RefreshPosition()


From my point of view, it is obvious that a property approach is much more clean and nice.


Tibit(Posted 2011) [#12]
I totally agree with Ziggy

You can do stuff like:
If myVector.Length < 10

Even cooler is that you can now also go:
myVector.Length = 40

My example was just for SET, but you can do GET properties aswell like Ziggy did, like this:

Method SState:Bool() Property
Return state
End
Method State:Void( value:Bool) Property
state = value
End

'close
Door.Open = False

'open
Door.Open = True

'Check
If Door.Open

' In this case (if it is appliciable to the game) you might want to check Close as well.

So you can go:
If Door.Close

'Or

Door.Close = True

All based on a isClosed:Bool or something more advanced. Actually since you use proper OOP abstraction (you do not access the object directly, only throught the interface) you can change that bool into a complex event system or something without changing the Open/Close Property