2007年4月8日星期日

Access Attributes

ActionScript 3 introduces 2 new access attributes for classes and members and refines the private attribute of ActionScript 2. In ActionScript 3 you have the following attributes for controlling access:

  • public
  • protected
  • private
  • internal (default)


public: The public attribute is the same as it was in ActionScript 2. Anything defined as public can be accessed anywhere by anything.

Constructors are always public.

Application classes need to be public.

protected: The protected attribute is a new attribute for ActionScript. It sets variables hidden from all access except from subclasses accessing the variables (inherited) from their own instance. Attempting to access a protected variable from another class instance in any circumstance will result in an error.

Classes and constructors cannot be defined as protected.

private: AS2 had the private attribute but it worked more like protected as subclasses had full access to private members. Now, with AS3, private is completely private and is only accessible from within the class in which it is defined. To all other classes, even subclasses, a private member doesn't even exist. This means that subclasses can even define new members of the same name and not have a conflict since the private member of the superclass is completely hidden. Private members are accessible directly off of class instances only when done so within the class definition.

Classes and constructors cannot be defined as private.

internal: Internal access is similar to public access but is restricted to package definitions. Classes in the same package have access to all internal members of any other class in that package. Classes in other packages do not have access.

Internal is the default for every class and class member except constructors which are always public.

Access control in helper classes are a little different. Since helper classes don't technically belong in packages, internal access for them is restricted to the classes in the current file. Helper classes themselves are inherently internal in this respect (and do not need to be explicitly provided any form of access attribute). Other access attributes within helper classes behave as expected. Note: your primary class cannot extend a helper class. Only helper classes can extend other helper classes and they need to be in the same file.

Something to keep in mind that access control for AS3 is also enforced not only during compile time, but also runtime. Hacks used in AS2 to get by accessing hidden methods will no longer work in AS3.

Example 1

ActionScript Code:

package {

import flash.display.Sprite;

// Application class needs to be public (internal by default)
public class AccessControl extends Sprite {

// constructors are always public
function AccessControl() {

// only classes in this file
// can access helper classes
var helper:Helper = new Helper();

trace(helper.pubNum); // OK
// trace(helper.protNum); // Error - cannot access protected
// trace(helper.privNum); // Error - cannot access private
trace(helper.interNum); // OK
}
}
}

// Helper class is implicitly internal
class Helper {

// public access granted anywhere
// variables are usually protected or
// private with get/set used for public access
public var pubNum:Number = 1;

// protected access granted only for
// subclasses in that class
protected var protNum:
Number = 2;

// private access granted only in this class
private var privNum:Number = 3;

// internal access granted only in the same
// package, but for helper classes, it means
// only in the same file
internal var interNum:
Number = 4;

// constructors are always public
function Helper() {
}
}

// SubHelper class is implicitly internal
// can extend other helper classes
class SubHelper
extends Helper {

// constructors are always public
function SubHelper() {
trace(pubNum); // OK
trace(protNum); // OK - inherited
// trace(privNum); // Error - cannot access private
trace(interNum); // OK
}
}


Example 2

ActionScript Code:

package {

import flash.display.Sprite;
import containers.*;

// Application class needs to be public (internal by default)
public class AccessControl extends Sprite {

// constructors are always public
function AccessControl() {

// can access classes in other packages
// only if public
var bowl:Bowl = new Bowl();
// OK
// var basket:Basket = new Basket(); // Error - cannot access internal

trace(bowl.pubNum); // OK
// trace(bowl.protNum); // Error - cannot access protected
// trace(bowl.privNum); // Error - cannot access private
// trace(bowl.interNum); // Error - cannot access internal
}
}
}

ActionScript Code:

package containers {

// public class accessible anywhere
public class Bowl {

// public access granted anywhere
public var pubNum:Number = 1;

// protected access granted only for
// subclasses in that class
protected var protNum:
Number = 2;

// private access granted only in this class
private var privNum:Number = 3;

// internal access granted only in the same package
internal var interNum:
Number = 4;

// constructors are always public
function Bowl() {

// can access inteneral classes if in same package
var basket:Basket = new Basket();

trace(basket.pubNum); // OK
// trace(basket.protNum); // Error - cannot access protected
// trace(basket.privNum); // Error - cannot access private
trace(basket.interNum); // OK - same package

// clone using public method
var basketCopy:Basket = basket.
clone();
}
}
}

ActionScript Code:

package containers {

// interal only accessible
// from other classes in package
internal class Basket {

// public access granted anywhere
public var pubNum:Number = 1;

// protected access granted only for
// subclasses in that class
protected var protNum:
Number = 2;

// private access granted only in this class
private var privNum:Number = 3;

// internal access granted only in the same package
internal var interNum:
Number = 4;

// constructors are always public
function Basket() {
}

// accessible anywhere as long as
// referencing a Basket instance
public function clone():Basket {
var basket:Basket = new Basket();
basket.
pubNum = pubNum; // OK
basket.
protNum = protNum; // OK - same class
basket.
privNum = privNum; // OK - same class
basket.
interNum = interNum; // OK
return basket;
}
}
}

0 评论: