不使用继承来轻松获得被保护变量 Access protected/default Variables Without Inheritance in AS3

png-0025 在Flex中,为了获得较大的控制权,我们往往需要获得被保护的变量。举例来说,有一个TextArea被用来输出log。一般的情况下,每增加一行log, 我们直接将TextArea scroll到底部,所以最新的log信息一直可以被看到。然而有时从服务器返回的log有几百行至多,如果TextArea直接翻到底部,用户不得不向上翻(最重要的信息往往在前面)。我们的目标是每次log被加到TextArea,显示新加log信息的第一行。实现这个,我们必须使用TextArea.textField (protected) 或 TextArea.getTextField(internal, default)以获得行数信息。

这里有两种实现的方法:

  1. 直接但设计较差的是:MyTextArea extends TextArea, 创建一个public函数返回textField即可。但这意味着我们想将log从TextArea class转而使用MyTextArea. 为了获取很小的功能,而大费周章。更为严重的是,后来的开发者会思考:为什么不直接用TextArea而用MyTextArea?
  2. 第二种考量是:TextAreaAccessor, 在mx.controls包内:
package mx.controls {
import mx.core.IUITextField;
import mx.core.mx_internal;
use namespace mx_internal;

public class TextAreaAccessor {
  /**
   * Returns the protected text field
   */
  public static function getTextField(textArea:TextArea):IUITextField {
    return textArea.getTextField(); // textArea.textField;
  }
} // end class
} // end package

我们可以这样做,是基于一个事实:internal(default) 的变量访问范围是same package,TextArea.getTextField()正是internal (default)且在mx_internal namespace之中。

理论上来讲,我们可以把TextAreaAccessor放在其他包内,令其extends TextArea, 这样getTextField(textArea)函数还是可以成功获取text field,但Flash Builder报错 - 在Java中这样做是被允许的。

获得了TextField,我们可以轻松实现人性化的log信息翻转。公司开发部同仁可以使用下面的方法来log信息到任意TextArea:

TextAreaUtils.appendMessageAndScrollProperly(textArea, mesg);