配列の例:PlayList

Flash Player 9 以降、Adobe AIR 1.0 以降

ここでは PlayList の例を使って、配列を操作する手法について、曲のリストを管理する音楽プレイリストアプリケーションのコンテキストで示します。 それらの手法は、次のとおりです。

  • インデックス配列の作成

  • インデックス配列への項目の追加

  • 各種ソートオプションを使用したオブジェクト配列のプロパティ別ソート

  • 文字で区切られたストリングへの配列の変換

このサンプルのアプリケーションのファイルを入手するには、 www.adobe.com/go/learn_programmingAS3samples_flash_jp を参照してください。 PlayList アプリケーションのファイルは、Samples/PlayList フォルダーにあります。 このアプリケーションは次のファイルで構成されています。

ファイル

説明

PlayList.mxml

または

PlayList.fla

Flash(FLA)または Flex(MXML)のメインアプリケーションファイル。

com/example/programmingas3/playlist/PlayList.as

曲のリストを表すクラス。1 個の Array を使用してリストを格納し、リスト項目のソート順を管理します。

com/example/programmingas3/playlist/Song.as

単一の曲に関する情報を表す値オブジェクト。 PlayList クラスが管理する項目は Song インスタンスです。

com/example/programmingas3/playlist/SortProperty.as

利用可能な値が Song クラスのプロパティを表し、このプロパティで Song オブジェクトのリストをソート可能な擬似列挙。

PlayList クラスの概要

PlayList クラスは Song オブジェクトセットを管理するクラスで、 曲をプレイリストに追加するための addSong() メソッドや、リストの曲をソートするための sortList() メソッドなど、様々な機能のパブリックメソッドを備えています。このクラスには、読み取り専用アクセッサープロパティの songList もあり、これによってプレイリストの実際の曲セットにアクセスできます。内部的には、PlayList クラスは、Array プライベート変数を使用して曲を追跡し続けます。

public class PlayList 
{ 
    private var _songs:Array; 
    private var _currentSort:SortProperty = null; 
    private var _needToSort:Boolean = false; 
    ... 
}

PlayList クラスが曲のリストを追跡し続けるために使用する _songs という Array 変数のほかに、2 つのプライベート変数( _needToSort _currentSort )があり、前者はリストのソートが必要であるかどうかを、後者は指定の時刻にどのプロパティで曲のリストをソートするかを追跡し続けます。

すべてのオブジェクトの場合と同様に、Array インスタンスを宣言するだけでは Array の作成作業は完了しません。 Array インスタンスのプロパティまたはメソッドにアクセスする前に、このインスタンスを PlayList クラスのコンストラクターでインスタンス化しておく必要があります。

    public function PlayList() 
    { 
        this._songs = new Array(); 
        // Set the initial sorting. 
        this.sortList(SortProperty.TITLE); 
    }

コンストラクターの 1 行目は、 _songs 変数をインスタンス化して使用できる状態にします。さらに、 sortList() メソッドを呼び出し、最初のソート基準プロパティを設定します。

リストへの曲の追加

ユーザーが新しい曲をアプリケーションに登録すると、データ入力フォームのコードが PlayList クラスの addSong() メソッドを呼び出します。

    /** 
     * Adds a song to the playlist. 
     */ 
    public function addSong(song:Song):void 
    { 
        this._songs.push(song); 
        this._needToSort = true; 
    }

addSong() 内では、 _songs 配列の push() メソッドが呼び出され、その配列の新しい要素として addSong() に渡された Song オブジェクトが追加されます。 push() メソッドでは、以前に適用していたソートとは関係なく、新しい要素を配列の末尾に追加します。つまり、 push() メソッドを呼び出した後では、曲のリストはソート順が正しくなっていない可能性が高いため、 _needToSort 変数は true に設定されます。理論上は、 sortList() メソッドをすぐに呼び出すため、指定の時刻にリストをソートするかどうかを追跡し続けることは不要になります。しかし、実際には、取得する直前まで曲のリストをソートする必要はありません。 例えば、取得前に何曲かリストに追加したときなど、ソート操作を遅らせると、アプリケーションは不要なソートを実行しなくなります。

曲のリストのソート

プレイリストが管理する Song インスタンスは複雑なオブジェクトであるため、そのアプリケーションのユーザーは、曲のタイトルまたは発表の年など、様々なプロパティに従ってプレイリストをソートしたいと考えることがあります。 PlayList アプリケーションにおいて、曲のリストをソートするタスクは、リストのソート基準としてのプロパティを見分けること、そのプロパティによるソート時に必要なソートオプションを指定すること、実際のソート操作を実行することの 3 つの部分から構成されます。

ソートのプロパティ

Song オブジェクトは、曲のタイトル、アーティスト、発表の年、ファイル名、およびユーザーの選曲ジャンル集など、いくつものプロパティを追跡し続けます。 言うまでもなく、ソートに実用的なのは、例に挙げた最初の 3 つのプロパティのみです。 開発者の便宜のため、例に含めた SortProperty クラスは、ソートに利用可能なプロパティを表す値を持つ列挙として機能します。

    public static const TITLE:SortProperty = new SortProperty("title"); 
    public static const ARTIST:SortProperty = new SortProperty("artist"); 
    public static const YEAR:SortProperty = new SortProperty("year");

SortProperty クラスには、 TITLE ARTIST 、および YEAR の 3 つの定数があり、各定数には、ソートに使用する関連 Song クラスプロパティの実際の名前を含むストリングが格納されます。コードの残り全体を通し、ソートプロパティが指定されると必ず列挙メンバーを使用して行われます。 例えば、PlayList コンストラクターでは、次のように、 sortList() メソッドを呼び出してリストを最初にソートします。

        // Set the initial sorting. 
        this.sortList(SortProperty.TITLE);

ソートのプロパティは SortProperty.TITLE として指定されているため、曲はタイトルに従ってソートされます。

プロパティによるソートおよびソートオプションの指定

実際には曲のリストのソートは、次に示すように、PlayList クラスが sortList() メソッドで実行します。

    /** 
     * Sorts the list of songs according to the specified property. 
     */ 
    public function sortList(sortProperty:SortProperty):void 
    { 
        ... 
        var sortOptions:uint; 
        switch (sortProperty) 
        { 
            case SortProperty.TITLE: 
                sortOptions = Array.CASEINSENSITIVE; 
                break; 
            case SortProperty.ARTIST: 
                sortOptions = Array.CASEINSENSITIVE; 
                break; 
            case SortProperty.YEAR: 
                sortOptions = Array.NUMERIC; 
                break; 
        } 
         
        // Perform the actual sorting of the data. 
        this._songs.sortOn(sortProperty.propertyName, sortOptions); 
             
        // Save the current sort property. 
        this._currentSort = sortProperty; 
 
        // Record that the list is sorted. 
        this._needToSort = false; 
    }

タイトルやアーティストによってソートする場合はアルファベット順にソートし、年によってソートする場合は数値順にソートします。 switch ステートメントを使用して、 sortProperty パラメーターが指定する値に従った適切なソートオプション(変数 sortOptions に格納)を定義します。ここでも、プロパティの区別には、ハードコードされた値ではなく名前付き列挙メンバーを使用しています。

ソートプロパティおよびソートオプションの決定に続き、 _songs 配列を sortOn() メソッドの呼び出しで実際にソートし、それらの 2 つの値をパラメーターとして渡します。現在のソートプロパティが記録されますが、それは曲のリストが現時点でソートされたということです。

文字で区切られたストリングへの配列要素の結合

配列を使用して曲のリストを PlayList クラスで維持する以外に、この例では Song クラスでも配列を使用して、曲についてのジャンルリストを管理するのに役立てています。 次の例で、Song クラスの定義からこのコードについて考えます。

private var _genres:String; 
 
public function Song(title:String, artist:String, year:uint, filename:String, genres:Array) 
{ 
    ... 
    // Genres are passed in as an array 
    // but stored as a semicolon-separated string. 
    this._genres = genres.join(";"); 
}

新しい Song インスタンスの作成時に、曲のジャンルの指定に使用する genres パラメーターが Array インスタンスとして定義されます。そのため、複数のジャンルを一緒のグループにまとめ、コンストラクターに渡せる 1 つの変数とするのに便利です。 ただし、内部的には Song クラスは、セミコロンで区切られた String インスタンスとして _genres プライベート変数にジャンルを維持します。Array パラメーターは、リテラルストリング値「 ; 」を区切り文字として指定して join() メソッドを呼び出すと、セミコロンで区切られたストリングに変換されます。

同じように、 genres アクセッサーを使用して、ジャンルを配列として設定また取得できます。

    public function get genres():Array 
    { 
        // Genres are stored as a semicolon-separated String, 
        // so they need to be transformed into an Array to pass them back out. 
        return this._genres.split(";"); 
    } 
    public function set genres(value:Array):void 
    { 
        // Genres are passed in as an array, 
        // but stored as a semicolon-separated string. 
        this._genres = value.join(";"); 
    }

genres set アクセッサーの動作は、コンストラクターの動作とまったく同じです。配列を受け取って join() メソッドを呼び出し、セミコロン区切りのストリングに変換します。 get アクセッサーは反対の操作を実行します。つまり、 _genres 変数の split() メソッドが呼び出されると、指定された区切り文字(リテラルストリング値 ";" など)を使用して、ストリングを値の配列に分割します。