Your Private Vars Might Not Be Private

In trying to create a read-only property for your class, you declare a private variable with a public getter. By omitting the public setter, you feel confident that you’ve just created a read-only property. However, not all variable types are created equal. In this entry I’ll examine a case where a property mistaken for being read-only is actually modified outside it’s class and how to avoid this gotcha.

Most of the primitive object types such as String, Number and Boolean are perfectly safe to implement as read-only using just private declaration and a public getter. This is because assigning the value of one of these variables to another variable actually assigns the value and not a reference to the value. Here’s an example in action:

class MyClass
{
  private var _foo:Number;
  public function get Foo ():Number
  {
    return _foo;
  }
  public function MyClass ()
  {
    _foo = 12;
  }
}
var oTest:MyClass = new MyClass();
var n:Number = oTest.Foo;
trace(oTest.Foo);  // 12
n = 34;
trace(oTest.Foo);  // 12

However, an object type like Array can’t be protected the same way because assigning an Array variable to another variable just assigns a reference to the original Array, not a copy of it. Therefore, you need to take additional measures when using an Array. Here’s an example of a private Array property failing to be read-only.

class MyClass
{
  private var _aryFoo:Array;
  public function get Foo ():Array
  {
    // You are returning a reference to this array not it’s value
    return _aryFoo;
  }
  public function MyClass ()
  {
    _aryFoo = new Array("a","b","c");
  }
}
var oTest:MyClass = new MyClass();
var a:Array = oTest.Foo;
trace(oTest.Foo);  // a,b,c
a[0] = "z";
trace(oTest.Foo);  // z,b,c

To protect the Array as read-only you need to return a copy of the Array instead of a reference to the Array. This is how you would do it if your Array was an array of Strings.

class MyClass
{
  private var _aryFoo:Array;
  public function get Foo ():Array
  {
    // You are returning a copy of the array
    return _aryFoo.slice(0);
  }
  public function MyClass ()
  {
    _aryFoo = new Array("a","b","c");
  }
}
var oTest:MyClass = new MyClass();
var a:Array = oTest.Foo;
trace(oTest.Foo);  // a,b,c
a[0] = "z";
trace(oTest.Foo);  // a,b,c

However, additional work is required when dealing with Arrays of other Arrays or Arrays of Objects to ensure you aren’t returning an Array of references even though you are return a copy of the Array. In the previous example, slice(0) was all that was needed because Strings return values and not references.

One Response to “Your Private Vars Might Not Be Private”

  1. Mark Lapasa Says:

    Nice Tip! I like

Leave a Reply


Bad Behavior has blocked 605 access attempts in the last 7 days.