Macromedia Flash非公式テクニカルノート ActionScript 2.0と1.0の継承について
Platform: All オブジェクト指向プログラミングにおける大きな特徴のひとつが、「継承」(inheritance)という仕組みです。「継承」とは、あるクラスをもとにして、別のクラスをつくることです。継承元のクラスをスーバークラス・親クラス・基本クラスなどといい、継承してつくられたクラスをサブクラス・子クラス・派生クラスなどといいます(Wikipedia「クラス」参照)。 継承は「拡張」(extension)と呼ばれることもあります。実際、ActionScript 2.0ではextendsというキーワードを使って、継承するスーパークラスを定義します。ActionScript 1.0では、Function.prototypeプロパティを使用して、継承を行います。 ActionScript 2.0のextendsキーワードの実装は、1.0の継承とは異なる点があります。それぞれの継承の内容と、ActionScript 2.0でFlash Player 6をターゲットとして書出した場合について簡単にご説明します。 1. ActionScript 1.0の継承 コンストラクタからつくられたインスタンスは、Object.__proto__プロパティをもちます。Object.__proto__プロパティは、コンストラクタ関数のFunction.prototypeプロパティを参照します。インスタンスをターゲットにしてメソッドやプロパティにアクセスしたとき、インスタンス自身がそれらを持ち合わせていなければ、Object.__proto__プロパティの参照先からメソッドやプロパティを呼出そうとします。 ActionScript 1.0においては、このようなコンストラクタ関数のprototypeとインスタンスの__proto__というふたつのプロパティを利用して、継承が行われます。スーパークラスのインスタンスを生成すると、そのインスタンスの__proto__プロパティは、スーパークラスのコンストラクタ関数のprototypeプロパティを参照します。したがって、このスーパークラスのインスタンスを、サブクラスのコンストラクタ関数のprototpeプロパティに設定すれば、サブクラスはスーパークラスを継承することになります[*1][*2]。
// フレームアクション この継承方法を使う場合に注意すべき点は、第1にスーパークラスのインスタンスでサブクラスのFunction.prototypeブロパティを書替えていることです。したがって、サブクラスにプロパティやメソッドを定義する前に、継承は済ませておかなければなりません。そうしないと、プロパティやメソッドの設定されたFunction.prototypeブロパティを、上書きしてしまうことになります。 注意点の第2は、継承時に必ずスーパークラスを呼出す必要があることです。たとえば、サブクラスのインスタンスを生成するときに、初期設定値をスーパークラスに渡したい場合を考えてみましょう(スクリプト001)。 スクリプト001■サブクラスからスーパークラスに初期設定値を渡す
[出力]の1行目は、継承を設定するときに、引数なしでスーパークラスが呼出された結果です。そして、2行目が、実際にインスタンスを生成する際の呼出しということになります。継承の設定時には、インスタンスを作成すること自体は目的ではありません。継承さえ行われればよいので、初期設定の処理は不要です[*3]。しかし、この継承時のスーパークラス呼出しは、やむを得ない副次的な効果といえます。
継承がサブクラスのコンストラクタ関数に備わるprototypeオブジェクトの__proto__プロパティにスーパークラスのコンストラクタのprototypeを設定することだとすれば、つぎのステートメントの方が論理的には優れています。サブクラスのコンストラクタのprototypeプロパティ自体を上書きすることがなく、スーパークラスも呼出されないからです。 Subclass.prototype.__proto__ = Superclass.prototype; ところが、「ActionScriptコーディングガイド」(PDF)は、「この方法はMacromedia Flash Player 6ではサポートされなくなり、勧められません」と、明確に否定します。実際上も、このObject.__proto__プロパティによる継承(いわゆる「__proto__継承」)は、super演算子でスーパークラスを呼出そうとしたときに問題が生じます。したがって、ActionScript 1.0では、サブクラスのコンストラクタ関数のprototypeプロパティに、スーパークラスのインスタンスを生成して設定する、前述の継承(いわゆる「new継承」)が推奨されます。 2. ActionScript 2.0の継承 class Subclass extends Superclass { もっとも、SWFに書出されるバイトコード(Flash Player向けの中間言語)は、ActionScript 1.0が使用するものと基本的に違いがありません(『FLASH OOP − ActionScriptによるオブジェクト指向プログラミング』p.025「ActionScript 2.0 − コンパイル時実装」)。つまり、ActionScript 2.0のクラスの処理も、内部的にはプロトタイプベース[*4]で行われていることになります。
実際、「Macromedia Flash (SWF) File Format Specification Version 7」(File Format Specification License Agreementからダウンロード)p.90によれば、ActionScript 2.0のextendsキーワードは、ActionScript 1.0のつぎのスクリプトと同じ扱いになります。 Subclass.prototype.__proto__ = Superclass.prototype; これは、Flash Player 6ではサポートしないとされたObject.__proto__プロパティによる継承(「__proto__継承」)が、ActionScript 2.0を使用したFlash Player 7のSWFに採用されたことを意味します。なお、Object.__constructor__は、ドキュメントには記載されていないプロパティです[*5]。
3. ActionScript 2.0の継承をFlash Player 6で書出した場合 図001■[パブリッシュ設定]ダイアログの[Flash]タブでPlayerとActionScriptのバージョンを設定 サブクラスのコンストラクタ関数から、super演算子でスーパークラスのコンストラクタに引数を渡して呼出す例を見てみましょう(スクリプト002)[*6]。 スクリプト002■ActionScript 2.0でサブクラスからスーパークラスに初期設定値を渡す
サブクラスのインスタンスを生成すると、サブクラスのコンストラクタ関数からスーパークラスが呼出されて、引数が渡されますので、結果はつぎのようになります。
この書出しをFlash Player 6にすると、[出力]結果がつぎのように変化します。
trace()ステートメントによる出力が、最初に1行加わっています。スーパークラスが引数なしで呼出されている[*7]ことから、サブクラスのコンストラクタ関数のprototypeプロパティにスーパークラスのインスタンスを生成して設定する、ActionScript 1.0の継承(「new継承」)が行われていると考えられます。ActionScript 2.0のバイトコードが1.0と基本的に同じであっても、書出すFlash Playerのバージョンによって内容の異なることがある点には注意が必要でしょう。
_____ 作成者: 野中文雄 Copyright © 2001-2006 Fumio Nonaka. All rights reserved. |
||||||||||||||