ActionScript3.0の修飾子とnamespaceまとめ
どうもtaroです.
最近案件で、自分以外の人がコードを拡張するようなものをやっています.
コーディングのスタイルとして、色んな変数をpublicにしすぎるのは良くないというのは、ありますが、 普段の仕事で、あまりprivate, protected, publicの違いを強く意識することはありませんでした.
少し簡単なまとめをしてみます.ご存知の項目も結構多いかもしれませんが、適宜読み飛ばしてください.
private, protected, public
internal | 同じpackage内から参照できる. |
private | 同じクラス内のみから参照できる. |
protected | 同じクラス及び派生したクラスから参照できる. |
public | 何処からでも参照できる. |
private, protected, public等をvar, function, constの前に付けて、それぞれのアクセス属性を設定することができますが、もし省略すると デフォルトはinternalになります.
コンストラクタをpublic以外で宣言することは出来ませんので、コンストラクタの場合だけデフォルトはpublicとなります.
internal
internalを使う場合はあまり無いかもしれませんが、例えばパーティクル系のエフェクト・ライブラリを提供する場合、共通で使うParticleクラス はそのライブラリのパッケージ内のinternalにしておくと、他のParticleという名前のクラスと衝突が起きなくて済みます.
private
同じクラスからしか参照できません.他のクラスでは使わないようなものをprivateに設定します.
protected
派生クラス(extendしたクラス)からも参照できるようにします.
プロジェクトで使いまわせそうな部分をベースのクラスにまとめておいて、 拡張するクラスから扱いたい変数や、メソッドをprotectedにするといった使い方でしょうか.
public
外部クラスからも使うようなものをpublicに指定します.
一覧表です。
クラス | メソッド | 変数・定数 | コンストラクタ | namespace | |
dynamic | ○ | × | × | × | × |
final | ○ | ○ | × | × | × |
internal | ○ | ○ | ○ | × | × |
private | × | ○ | ○ | × | ○ |
protected | × | ○ | ○ | × | ○ |
public | ○ | ○ | ○ | ○ | ○ |
static | × | ○ | ○ | × | × |
static
これはメソッドや変数・定数がクラスのインスタンスでなく, クラスに属していることを表す修飾詞です.
注意しないといけないのは、クラスの継承関係は無視するということです。
class A { static public var ID:String = "a"; } class B extends A { }
この例で、B.IDというアクセスは出来ません.
これはIDという変数がクラスAにのみ属しているからです.
同様の理由で、staticなものをoverrideすることは出来ません.
親のクラスと子のクラスのstaticなメソッド、変数、定数はそれぞれ別物として扱われます.
dynamic
これは、クラスのインスタンスに動的にプロパティーが追加できるようなクラスです.
var d:D = new D(); d.movie = new MovieClip(); dynamic class D { }
dynamicでないクラスのインスタンスに対してmovieといったクラス内で予め宣言されていないプロパティに アクセスすることは出来ません.
また、dynamicであるという性質は継承関係のあるクラスに引き継がれません.
これは、全てのクラスがdynamicなクラスObjectの拡張であることからも分かります.
ビルトインのクラスでdynamicなクラスとして表的なものは、Object, Array, MovieClip, URLVariables, Dictionary
等が挙げられます.
namespace
namesapaceには色々使い方があると思います.
弊社道家がnamespaceの実用的な使用例を 別エントリで書いておりますので、興味がございましたらこちらもご一読下さい.
ライブラリを提供するとき、ライブラリの外部から余りアクセスして欲しくないようなメソッド、変数というのがあります.
例えば、前回ご紹介したBox2Dの開発バージョンには、Box2D.Common.b2internalというnamespace が用意されていて、アクセス・コントロールをしています.
namespace _level0 = "http://level0.kayac.com/"; var un:UsingNamespace = new UsingNamespace(); un.setName("taro"); // un._level0::name = "taro" class UsingNamespace { _level0 var name:String; public function setName(value:String):void { _level0::name = value; } }
このコードで_level0というnamespaceに割り当てられた変数nameにアクセスするには、クラスの中からは、_level0::nameのようにアクセスします.
クラスの外からこれらのnamespaceがついている変数、メソッドにアクセスするには、un._level0::nameのようにすればアクセスできます.
少し気持ち悪いですね.
use namespace _level0
としていれば、_level0というのを書かずにアクセス出来ます.
wonderflのページにもサンプル・コードを 挙げてみました.
ライブラリなどで使うとき、namespaceはクラスの外に書いて他のクラスからも同じnamespaceにアクセスできるようにした方がが便利なので、 クラス外に書くことが多いかもしれません.
この書き方については、後述します.
constructor
コンストラクタについての注意点を幾つか.
コンストラクタはpublicで返値を持ちません.
Singletonを作るとき、他の言語でコンストラクタをprivateにして隠蔽するという方法がありますが、ActionScript3.0では出来ません.
コンストラクタを省略すると、デフォルト・コンストラクタといって何も処理を走らせない関数が走ります.
AS初心者の去年、デフォルトコンストラクタにしていて後から、コンストラクタを手動で書いたときに、タイプ・ミスでコンストラクタではない、 良く似た名前の別の関数を作っていたのに気づかなかったという思い出があります.
コンストラクタが無くてもコンパイル・エラーにはならないですからね.
public class Thumbnail extends Sprite { public function Thumbnial () { // タイプ・ミス // 初期化の処理 } }
Flex系のコンパイラだとちゃんと関数に型宣言がありませんという警告をくれるのですが、Flash CS3では警告をだしません.(設定すれば出るのかもしれませんが。。。)
Flex系の厳しいコンパイラはある意味では親切かもしれません.
無名コンストラクタと呼ばれるものがありますが、それについては別エントリをご覧下さい.
クラス外のfunction, namespace
import文でクラスをimportしますが、クラス以外のものをimportすることがあります.
flash.net.navigateToURL等はその典型的な例でしょう.
ここでimportされているのは関数です.
package com.kayac.level0.utils { public function utilityFunction():void { } }
のような書き方をして、utilityFunction.asとして保存すれば同じようなことが出来ます.
package com.kayac.level0 { public namespace _level0 = "http://level0.kayac.com"; }
等のようにして_level0.asと保存しておけば、同じnamespaceを複数のクラスで共有できます.