パッケージ

ActionScript 3.0 では、パッケージは名前空間で実装されますが、名前空間と同義ではありません。パッケージを宣言すると、コンパイル時に必ず既知である名前空間が暗黙的に作成されます。名前空間は、明示的に作成された場合はコンパイル時に既知である必要はありません。

次の例では、package ディレクティブを使用して、クラスを 1 つ含む単純なパッケージを作成します。

package samples
{
    public class SampleCode
    {
        public var sampleGreeting:String;
        public function sampleFunction()
        {
            trace(sampleGreeting + " from sampleFunction()");
        }
    }
}

この例のクラスの名前は SampleCode です。クラスは samples パッケージ内にあるので、コンパイラはコンパイル時にクラス名を自動的に修飾し、完全修飾名の samples.SampleCode にします。また、コンパイラはプロパティやメソッドの名前も修飾するので、sampleGreeting および sampleFunction() は、それぞれ samples.SampleCode.sampleGreeting および samples.SampleCode.sampleFunction() になります。

多くの開発者、特に Java 開発者は、パッケージの最上位にクラスだけを配置することを選択します。しかし、ActionScript 3.0 では、パッケージの最上位でクラスだけではなく、変数、関数、ステートメントもサポートされています。この機能の高度な使用方法として、パッケージ内のすべてのクラスで使用できるようにパッケージの最上位で名前空間を定義できます。ただし、パッケージの最上位で指定できるアクセス指定子は publicinternal の 2 つだけです。ネストされたクラスをプライベート宣言できる Java と異なり、ActionScript 3.0 はネストされたクラスも、プライベートクラスもサポートしていません。

しかし、その他の多くの点で、ActionScript 3.0 のパッケージは Java のパッケージと似ています。前の例を見ればわかるとおり、完全修飾パッケージ参照は、Java と同じように、ドット演算子 (.) を使用して表します。パッケージを使用すると、他のプログラマも使用できるように、直感的な階層構造にコードを構成できます。これにより、独自のパッケージを作成して他のプログラマと共有したり、他のプログラマが作成したパッケージを利用したりでき、コードの共有が容易になります。

パッケージを使用することで、使用する識別子名が一意になり、他の識別子名と競合しなくなります。実際、これがパッケージの最も重要な利点であるという人もいます。たとえば、コードを共有しようとしている 2 人のプログラマがそれぞれ SampleCode というクラスを作成したとします。パッケージを使用しなければ、名前の競合が発生し、いずれかのクラスの名前を変更するしかなくなります。ただし、パッケージを使用すると、一意の名前を持つパッケージ内のクラスのいずれか、またはできれば両方を配置することによって、名前の競合は簡単に回避されます。

パッケージ名に埋め込みドットを入れて、ネストされたパッケージを作成することもできます。これにより、パッケージの階層構造を作成できます。その良い例は、Flash Player API によって提供される flash.xml パッケージです。flash.xml パッケージは、flash パッケージ内にネストされています。

flash.xml パッケージには、旧バージョンの ActionScript で使用されていた古い XML パーサーが含まれています。古い XML パーサーが flash.xml パッケージに置かれる理由の 1 つは、古い XML クラスの名前が、ActionScript 3.0 で使用可能な ECMAScript for XML 仕様の機能を実装する新しい XML クラスの名前と競合するためです。

古い XML クラスをパッケージに移動するのは最初の手順として適していますが、古い XML クラスを使用するほとんどの場合で、flash.xml パッケージが読み込まれます。この場合も、必ず古い XML クラスの完全修飾名 (flash.xml.XML) を使用しなければ、同じ名前の競合が発生します。この問題を回避するために、古い XML クラスは、次の例に示すように XMLDocument という名前になりました。

package flash.xml
{
    class XMLDocument {}
    class XMLNode {}
    class XMLSocket {}
}

Flash Player API のほとんどは flash パッケージにあります。たとえば、flash.display パッケージには表示リスト API が含まれ、flash.events パッケージには新しいイベントモデルが含まれています。

パッケージの作成

ActionScript 3.0 では、パッケージ、クラス、およびソースファイルを整理する方法に大きな柔軟性を持たせています。旧バージョンの ActionScript では、ソースファイルごとにクラスが 1 つだけ許可され、ソースファイルの名前がクラスの名前と一致する必要がありました。ActionScript 3.0 では、1 つのソースファイルに複数のクラスを含めることができますが、ファイルの外部にあるコードで使用できるのは各ファイルのクラス 1 つだけです。つまり、各ファイルのクラスを 1 つだけパッケージ宣言内で宣言できます。その他のクラスはパッケージ定義の外部で定義する必要があります。これにより、追加されるクラスはソースファイル外部にあるコードに対して表示されなくなります。パッケージ定義内で定義されたクラスの名前は、ソースファイルの名前に一致している必要があります。

ActionScript 3.0 では、パッケージをより柔軟に宣言することができます。旧バージョンの ActionScript では、パッケージはソースファイルを配置するディレクトリを表すだけでした。また、package ステートメントでパッケージを宣言するのではなく、クラス宣言内の完全修飾クラス名の一部としてパッケージ名を含めていました。ActionScript 3.0 でもパッケージはディレクトリを表しますが、パッケージに含めることができるのはクラスだけではありません。ActionScript 3.0 では、package ステートメントを使用してパッケージを宣言します。つまり、パッケージの最上位で変数、関数、および名前空間を宣言することもできます。パッケージの最上位に実行可能ステートメントを含めることもできます。パッケージの最上位で変数、関数、または名前空間を宣言した場合は、そのレベルで使用できる属性は public および internal だけです。また、この宣言がクラス、変数、関数、または名前空間のいずれであるかに関係なく、public 属性を使用できるのはファイルごとにパッケージレベルの宣言 1 つだけです。

パッケージは、コードを構成したり、名前のコンフリクトを防いだりするのに便利です。パッケージの概念および関連のないクラス継承の概念を混同しないようにしてください。同じパッケージ内にある 2 つのクラスには共通する名前空間がありますが、この 2 つのクラスはその他で関連しているとは限りません。同様に、ネストされたパッケージは、親パッケージと意味的な関係がない場合があります。

パッケージの読み込み

パッケージ内部にあるクラスを使用する場合、パッケージまたは使用するクラスを読み込む必要があります。これは、クラスの読み込みがオプションであった ActionScript 2.0 とは異なります。

たとえば、この章で前述した SampleCode クラスの例を考えてみます。クラスが samples という名前のパッケージにある場合、SampleCode クラスを使用する前に次の import ステートメントのいずれかを使用する必要があります。

import samples.*;

または

import samples.SampleCode;

一般的に、import ステートメントは可能な限り明確にします。samples パッケージから SampleCode クラスだけを使用する場合、属するパッケージ全体ではなく SampleCode クラスだけを読み込む必要があります。パッケージ全体の読み込みにより、予期しない名前の競合が発生する場合があります。

クラスパス内にパッケージまたはクラスを定義するソースコードを配置する必要もあります。クラスパスは、読み込むパッケージおよびクラスをコンパイラが検索する場所を決定するローカルディレクトリパスのユーザー定義リストです。クラスパスは "ビルドパス" または "ソースパス" と呼ばれることもあります。

クラスまたはパッケージを適切に読み込むと、クラスの完全修飾名 (samples.SampleCode) またはクラス名のみ (SampleCode) のいずれかを使用できます。

完全修飾名は同じ名前のクラス、メソッド、またはプロパティが存在してコードがあいまいになるときに役立ちますが、すべての識別子に使用すると管理が困難になる可能性があります。たとえば、SampleCode クラスのインスタンスをインスタンス化するときに完全修飾名を使用すると、コードが冗長になります。

var mySample:samples.SampleCode = new samples.SampleCode();

ネストされたパッケージのレベルが高くなるにつれて、コードの可読性が低下します。あいまいな識別子が問題ではないことが確実な場合、単純な識別子を使用してコードを読みやすくすることができます。たとえば、クラス識別子のみを使用する場合、SampleCode クラスの新しいインスタンスのインスタンス化はかなり簡単になります。

var mySample:SampleCode = new SampleCode();

最初に適切なパッケージまたはクラスを読み込まずに識別子の名前を使用しようとすると、コンパイラがクラス定義を検出できない場合があります。また、パッケージまたはクラスを読み込んだ場合は、読み込んだ名前と競合する名前を定義しようとすると、エラーが生成されます。

パッケージの作成時には、そのパッケージのすべてのメンバーのデフォルトのアクセス制御子は internal です。この場合、デフォルトではパッケージメンバーは、そのパッケージの他のメンバーに対してのみ表示されます。パッケージ外部のコードでクラスを使用できるようにする場合、public でクラスを宣言する必要があります。たとえば、次のパッケージには、SampleCode と CodeFormatter の 2 つのクラスが含まれています。

// SampleCode.as ファイル
package samples
{
    public class SampleCode {}
}

// CodeFormatter.as ファイル
package samples
{
    class CodeFormatter {}
}

SampleCode クラスは、public クラスとして宣言されるので、パッケージの外部に表示されます。しかし、CodeFormatter クラスは、samples パッケージ内にのみ表示されます。サンプルパッケージの外部にある CodeFormatter クラスにアクセスしようとすると、次の例に示すように、エラーが発生する場合があります。

import samples.SampleCode;
import samples.CodeFormatter;
var mySample:SampleCode = new SampleCode(); // OK、public クラス
var myFormatter:CodeFormatter = new CodeFormatter(); // エラー

パッケージ外部で両方のクラスを使用する場合、両方のクラスを public として宣言する必要があります。パッケージ宣言に public 属性を適用することはできません。

完全修飾名は、パッケージを使用するときに発生する可能性がある名前のコンフリクトを解決する際に役立ちます。たとえば、同じ識別子でクラスを定義する 2 つのパッケージを読み込む場合などです。たとえば、SampleCode という名前のクラスも持つ次のパッケージがあるとします。

package langref.samples
{
    public class SampleCode {}
}

次に示すように両方のクラスを読み込むと、SampleCode クラスの参照時に名前の競合が発生することがあります。

import samples.SampleCode;
import langref.samples.SampleCode;
var mySample:SampleCode = new SampleCode(); // 名前の競合

コンパイラには、どちらの SampleCode クラスを使用するのかを知る方法はありません。この競合を解決するには、次のように各クラスの完全修飾名を使用する必要があります。

var sample1:samples.SampleCode = new samples.SampleCode();
var sample2:langref.samples.SampleCode = new langref.samples.SampleCode();

メモ

 

C++ を使用していたプログラマは、import ステートメントと #include を混同しがちです。C++ コンパイラは一度に 1 つのファイルを処理するため、C++ では #include ディレクティブが必要で、このディレクティブはヘッダファイルが明示的に含まれていない限り、他のファイル内でクラス定義を探しません。ActionScript 3.0 には include ディレクティブがありますが、クラスやパッケージを読み込むように設計されていません。ActionScript 3.0 でクラスまたはパッケージを読み込むには、import ステートメントを使用して、パッケージを含むソースファイルをクラスパスに配置する必要があります。


 

このページに新しいコメントが追加された場合に、電子メールでの通知を希望する。 | コメントレポート

現在のページ: http://livedocs.adobe.com/flash/9.0_jp/main/00000041.html