PDA

View Full Version : Public Variables vs. get and set


Mazoonist
11-03-2008, 02:38 AM
Okay, I've been learning OOP principles bit by bit, and I'm reading a book about design patterns. I have read that you never want to use public variables, as it breaks encapsulation, and I understand all that, and really I understand why. However, suppose you're just doing a small project (or just goofing around, like me!), and you just need to create some quick classes that are only going to store some properties. On the one hand you can do this:
package {
public class Foo {
protected var bar:int;

public function set bar(value:int) {
bar = value;
}
public function get bar():int {
return this.bar;
}
}
}
Or, you could just do this:
package {
public class Foo {
public var bar:int;
}
}
Since in the first example, the get and set methods aren't doing anything other than passing along or retrieving the value directly--it would seem, in practice, it's identical to the second example. Is there NEVER a case where you would want to use public variables? Because the first example above becomes kind of unwieldy as you get more and more properties that you want the object to store. If you're not planning to filter the values in any way, why write getters and setters for all of them? I mean, really, what is the difference between the two above examples?? And how else would you do it?

Or, consider a built in class like MovieClip. Do they really have getters and setters for every property? Thanks in advance for any responses!

maskedMan
11-03-2008, 10:37 PM
Personally, I only break this rule in the case of custom events, which are really more just messengers than objects that are intended to stick around for any length of time. Why would I stick to it otherwise? Mainly it's because you don't always know when you'll need to track access to a variable. Yeah, you *could* go in and do it later, once it becomes apparent that you do, but it can be annoying to do that.

fx.barrett
11-03-2008, 11:09 PM
Or, consider a built in class like MovieClip. Do they really have getters and setters for every property? Thanks in advance for any responses!
If I'm not mistaking, then yeah, they do have getter and setter methods for all the stuff.

To be honest, I wasn't using getters and setters a year ago, I didn't even know what they exactly were... but since then, i've been using them all the time. And you are kinda right, I don't really declare my variables as public, I rather define a getter/setter if I want to modify them externaly...

I feel that it makes the code more readable and organized and something I really like about is that you can give a really long name to your variable but have a simply and clear getter / setter manipulate it:

Example:

// you might have a long name or a tiny name for a variable
// and it's purpose is obvious to everyone trough the class but that
// doesn't mean that you must use that long name outside the class too

private var currentyLoggedInUser:String = "John";

public function get currentUser():String
{
return this.currentyLoggedInUser;
}
Ok, my example might not be a perfect demonstration but I hope you get the idea.

I don't think that it's a must to define getters and setters for your vars but it definitely is considered a better practice then manipulating the variable directly. Some like getters, some don't, what matters is to have readable and non-ambiguous code.

Mazoonist
11-04-2008, 06:03 AM
Thanks guys, nice ideas. This has given me some more food for thought, I appreciate it.

yell0wdart
11-04-2008, 05:41 PM
You don't *need* them, but as far as best OO practices go, it's definitely a good thing to use them instead of directly accessing those variables. You don't always need to, obviously, but there are times when you want to control access to those variables with customized logic:


public class Person
{
private var personAddresses:Array = new Array();

public function get primaryAddress():Address
{
for each (var address:Address in this.addressCollection)
{
if (address.isPrimary())
return address;
else
return null;
}
}

// constructor, methods, etc to initialize Person object and load array...
}


The syntax may not be perfect, but you get the idea. Using getters and setters is better than the alternative...


// rather than
addressTextBox.text = person.addresses[0].streetAddress;

// you'd do
addressTextBox.text = person.primaryAddress().streetAddress;

// this would ensure you're always getting the Address object flagged as
// 'primary', rather than making an assumption... what if the first object
// in the array wasn't the primary address? what if the person object has
// no address?

Mazoonist
11-07-2008, 01:11 AM
Okay, I solved my own issue. What I did is wrote out all the getters and setters in an Abstract Base Class. When my other classes extend the Base Class, they inherit all those getter and setter methods. Even though it seems like a lot more work than writing public variables, I really only had to do it once, then all my derived classes just inherit them. And even though each one simply sets or returns the associated private property, in my derived classes I can always override that default behavior if I want to.

I had an idea for a cool project, and I want to do it up OOP style. I wonder if anyone here (some who knows good OOP practices, preferably) would be interested in helping me develop it. If so, send me a PM and I'd be glad to tell you more about it.

newblack
11-07-2008, 02:44 AM
getters/setters should really only be used:

if you're computing (directly or in a subclass) something when the property is being gotten or set
if you're typing to an interface.


otherwise they are superfluous, and, if anything, add computational overhead.

if you follow adobe convention, the protected or private property is identical to the getter/setter name, but prefixed with an underscore. as far as asdoc comments, the property gets marked @private, and the getter gets the commenting.

http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions

Mazoonist
11-07-2008, 02:54 AM
Hey newblack,

Thanks for the response. I've been reading a lot about design patterns, and I'm attempting, via an abstract class, to program to an interface. I've got a nice little inheritance chain happening. And in the above, the phrase "associated private property" should really read "associated protected property."

Flash Gordon
11-12-2008, 06:03 AM
if you follow adobe convention

http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions

Just want to point that that it's not necessarly an adobe convention but a convention used by people who develop on the open source flex framework


Some of these standards are completely arbitrary, since there is not always a “best way” to code. Nevertheless, in the interest of consistency, all commits to the Flex SDK project will be expected to follow these conventions.


I think the most important thing to take from that is consistency. There's nothing wrong with diverging from that document. If you're building a framework stick with 1 style for the whole thing. It's a nightmare when subclassing if you have some protected properties prepended with an underscore and some not

otherwise they are superfluous, and, if anything, add computational overhead.. Not to pick on newblack (he's awesome! and i do it too)...but let me just add you can't always anticipate when that is going to happen. It is easy enough to change later when need to a mutator/acessor but then you're class real isn't closed for modification and open for extension. (if it really matters for changing to a getter/setter). Yes, OOP does give overhead. Programming is often a trade of....take your pick.

NickZA
12-04-2008, 03:49 PM
100% agree with newblack -- if you are not applying any processing to the values, and they are read-write, don't waste your time with getters and setters. As mentioned, yes it will add overhead due to the scope change that occurs when you enter the relevant get or set function.

Assertnfailure
12-08-2008, 04:39 AM
Let me respond by mentioning how much I hate that the Point class uses public variables for x and y instead of getters/setters.

I wanted to create a Vector class that subclassed Point for additional vector-type logic, yet allowing it to seamlessly polymorph for any classes that use Point objects.

Unfortunately the class couldn't observe changes to the x and y values because I can't override and inject custom behavior.

bowljoman
12-08-2008, 05:17 AM
@ assertnfailure
Try this approach towards extending a flash base class such as 'Point';


package com.thebitstream
{
import flash.geom.Point;

public class PointExtended extends Point
{
public function PointExtended(x:Number=0, y:Number=0)
{
super(x, y);
}
public override function set x(val:Number):void
{
super.x=val;
}
public override function set y(val:Number):void
{
super.y=val;
}
}
}

Assertnfailure
12-08-2008, 07:29 AM
yeahh.....did you actually try that, bowljoman? It says incompatible override.
(btw I know how to override getters/setters)

creynders
12-08-2008, 03:11 PM
Yep, x and y are actual properties of the Point class. What a shame.
And to counter other posters: you should NEVER, EVER use public properties.
EVER.
IMO they should just get rid of public variables.

Have you tried using the Proxy class, Assert?
It's not a very clean solution, but it should work. Instead of inheriting from Point, inherit from Proxy and use composition for the Point object. Then using the flash_proxy methods intercept any calls to x and y and redirect them to your own accessors.

Assertnfailure
12-08-2008, 04:17 PM
Well, composition isn't a problem. I think ultimately, I just made it a standalone class that can create Point objects via one of its methods.

...I wanted to be able to pass it into the pre-built geom/bitmapdata classes though.