< Day Day Up > |
A new feature within ActionScript 2.0 gives us the ability to determine from where properties can be accessed. This is done with the keywords public and private . Public Versus PrivateMost object-oriented (as well as some procedural) languages share the ability to set the access rights to properties. Although other languages give many choices (public, protected, package, private, and so on) in setting access, ActionScript 2.0 gives us only two choices: public and private . A private element of a class can be accessed only from within the same object. In the "Data Hiding" section that follows , we'll discuss why this would be done. For now, note that a public element is available from other objects, movie clip instances, and so on. Listing 3.2 shows a modification on the Loan class from Chapter 2. This time, class is setting all the properties as private . Listing 3.2. Modifications to the Loan Class Show the Properties as Private Membersclass Loan{ private var principal:Number ; private var rate:Number ; private var years:Number ; ... }
Data HidingIt is nice to know that we have the ability to declare properties as private or public, but the real question is why would we? The concept of data hiding exists across all object-oriented languages. With an effective use of data hiding, any object can have its data effectively encapsulated within it. This follows the same object-oriented principles implemented in Java and C++, in that the details of how an object is implemented do not need to be understood by those using the object. For example, we do not need to know the implementation details of our car to be able to drive it. Regardless of whether a car has a carburetor or fuel injectors , whether the cams are overhead or not, we as users of the car do not change how we drive it. The properties of the car are hidden from us. Internally, the car knows about its properties and how to make use of them, but those details are not exposed to the driver behind the wheel. The same is true of objects. By hiding the details (such as properties), we as developers can determine the way a movie clip and other objects can interact with ours. This grants many benefits to development, including less confusing code implementations , less chance of developer error from interacting with properties whose true use is not understood, and easier integration of development teams consisting of experienced and less experienced developers. Frequently in OOP, we create methods to enable interactions with private properties. Figure 3.5 shows a failed attempt at directly interacting with a private property from an instance of the Loan class. Figure 3.5. The compiler prevents us from directly accessing private elements.
Getters and SettersIntegral to the idea of data hiding is providing an interface to enable controlled access to properties. By limiting developers access to properties through the use of methods, we can shield developers from potential changes to the underlying data of an object. If the properties names or datatypes should change, developers will not need to change their interactions with the object, so long as the methods that they are using to access the data remain consistent. They can simply modify the workings of the interface to reflect the new structure. The signature will remain the same. This means that as far as the rest of the system is concerned , nothing has changed. These interfaces are traditionally built as methods, which enable modification and retrieval of data from the object. These types of methods are generally referred to as getter and setter methods. Explicit Getters and SettersTraditional getter and setter methods have explicitly declared method names, such as getName() or setPrice() . These are referred to as explicit getters and setters because using them requires explicitly invoking their names. Listing 3.3 shows the explicit getters and setters of the Loan class. Listing 3.3. Explicit Getters and Setters Are Added to the Loan Class to Facilitate Interaction with Their Private Propertiesclass Loan{ private var principal:Number ; private var rate:Number ; private var years:Number ; function setPrincipal(thePrincipal:Number ) { if(thePrincipal > 0){ this.principal = thePrincipal; } else { trace("error, principal must be greater than 0"); } } function setRate(theRate:Number) { this.rate=theRate; } function setYears(theYears:Number ) { this.years=theYears; } function getYears( ):Number { return this.years; } function getRate( ):Number{ return this.rate; } function getPrincipal( ):Number{ return this.principal; } } There are two methods for each property, one named get<propertyName> and the other named set<propertyName> . Although the properties themselves are private, meaning that they are directly accessible only within the object, these methods enable the properties to be accessed externally. The setPrincipal method shows another benefit: data can be validated within the methods before it is added to the object.
Implicit Getters and SettersActionScript 2.0 has implemented another style of getter and setter methods, which they refer to as implicit getters and setter s. These implicit methods make use of the new keywords get and set within the method definition. This style of getter and setter methods is very similar to the constructs with the same names within C#. To declare an implicit getter method, the syntax is this: function get methodName(){}; Note that implicit setter methods use the keyword set in place of get .
Listing 3.4 shows the Loan class modified using implicit getter and setter methods. Listing 3.4. C#-Style Implicit Getters and Setters Are Used in Place of the More Traditional Getter and Setter Methods That Were Used Earlierclass Loan{ private var _principal:Number ; private var _rate:Number ; private var _years:Number ; function set principal(thePrincipal:Number ) { if(thePrincipal > 0){ this._principal = thePrincipal; } else { trace("error, principal must be greater than 0"); } } function set rate(theRate:Number) { this._rate=theRate; } function set years(theYears:Number ) { this._years=theYears; } function get years( ):Number { return this._years; } function get rate( ):Number{ return this._rate; } function get principal( ):Number{ return this._principal; } } A few changes were made structurally to accommodate the implicit getters and setters. To comply with the requirement that the method name not match the property names, the property names are modified and prefixed with an underscore (this is the same convention that the user interface [UI] components follow). Next, a series of functions are written using the get and set keywords. The internals of the methods are identical to the explicit methods we had before; the only difference is how they are defined. The odd thing about this style of method is how it is invoked. To use an implicit getter or setter method, it is called just like a property of the object, like so: var theLoan:Loan = new Loan(); theLoan.rate = 8; It looks like we are setting a property called rate . In reality, however, the object no longer has a property called rate ; instead, the property is named _rate . To illustrate this point, we can try to trace the _rate property, as well as the results of the implicit rate getter, as shown in Figure 3.6. Figure 3.6. A compile-time error is thrown trying to access the private property _rate .
At first glance, the use of implicit getters and setters may seem preferable, as developers using them can continue to believe they are interacting with the properties directly. However, we do not consider their use a best practice. The reason for this is that developers new to OOP should learn that they should not build objects that enable direct access over the objects properties. The use of implicit getters and setters lets these new developers believe that experienced developers are building objects that allow for direct access to properties. This is likely to lead to new developers not using proper encapsulation and data hiding.
|
< Day Day Up > |