Ejemplo de conjuntos: PlayList

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

El ejemplo PlayList ilustra técnicas para trabajar con conjuntos, en el contexto de una aplicación de lista de reproducción de música que administra una lista de canciones. Estas técnicas son:

  • Creación de un conjunto indexado

  • Añadir elementos a un conjunto indexado

  • Ordenación de un conjunto de objetos por distintas propiedades y utilizando distintas opciones de ordenación

  • Conversión de un conjunto en una cadena delimitada por caracteres

Para obtener los archivos de la aplicación de este ejemplo, consulte www.adobe.com/go/learn_programmingAS3samples_flash_es . Los archivos de la aplicación PlayList se encuentran en la carpeta Samples/PlayList. La aplicación consta de los siguientes archivos:

Archivo

Descripción

PlayList.mxml

o

PlayList.fla

El archivo de aplicación principal en Flash (FLA) o Flex (MXML).

com/example/programmingas3/playlist/PlayList.as

Una clase que representa una lista de canciones. Utiliza un elemento Array para guardar la lista y gestiona la ordenación de los elementos de la lista.

com/example/programmingas3/playlist/Song.as

Un objeto de valor que representa información sobre una sola canción. Los elementos administrados por la clase PlayList son instancias de Song.

com/example/programmingas3/playlist/SortProperty.as

Una seudoenumeración cuyos valores disponibles representan las propiedades de la clase Song por las que una lista de objetos Song puede ordenarse.

Información general sobre la clase PlayList

La clase PlayList administra un conjunto de objetos Song. Dispone de métodos públicos con funcionalidad para añadir una canción a la lista de reproducción (el método addSong() ) y ordenar las canciones de la lista (el método sortList() ). Además, la clase incluye una propiedad de descriptor de acceso de solo lectura, songList , que proporciona acceso al conjunto de canciones de la lista de reproducción. Internamente, la clase PlayList hace un seguimiento de sus canciones mediante una variable privada de tipo Array:

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

Además de la variable _songs de tipo Array utilizada por la clase PlayList para hacer un seguimiento de su lista de canciones, otras dos variables privadas hacen un seguimiento de si la lista debe ser ordenada ( _needToSort ) y por qué propiedad está ordenada la lista de canciones en un momento dado ( _currentSort ).

Al igual que ocurre con los objetos, declarar una instancia de Array es solo la mitad del trabajo de crear un objeto Array. Antes de acceder a las propiedades o métodos de una instancia de Array, hay que crear una instancia en el constructor de la clase PlayList.

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

La primera línea del constructor crea una instancia de la variable _songs lista para usar. Además, se llama al método sortList() para establecer la propiedad por la que se va a ordenar inicialmente.

Añadir una canción a la lista

Cuando un usuario introduce una nueva canción en la aplicación, el código del formulario de entrada de datos llama al método addSong() de la clase PlayList.

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

En addSong() , se llama al método push() del conjunto _songs , para añadir el objeto Song que se pasó a addSong() como un elemento nuevo del conjunto. Con el método push() se añade el nuevo elemento al final del conjunto, independientemente de la ordenación que se haya aplicado previamente. Esto significa que tras llamar al método push() , es probable que la lista de canciones ya no esté ordenada correctamente, por lo que se establece la variable _needToSort en true . En teoría, el método sortList() podría llamarse inmediatamente, lo que eliminaría la necesidad de controlar si la lista está ordenada o no en un momento determinado. No obstante, en la práctica no es necesario ordenar la lista de canciones hasta inmediatamente antes de recuperarla. Al aplazar la operación de ordenación, la aplicación no realiza una ordenación innecesaria si, por ejemplo, se añaden varias canciones a la lista antes de recuperarla.

Ordenación de la lista de canciones

Como las instancias de Song administradas por la lista de reproducción son objetos complejos, es posible que los usuarios de la aplicación deseen ordenar la lista de reproducción según distintas propiedades, como el título de la canción o el año de publicación. En la aplicación PlayList, la tarea de ordenación de la lista de canciones tiene tres partes: identificación de la propiedad con la que se debe ordenar la lista, indicación de las opciones de ordenación que se deben utilizar al ordenar con dicha propiedad y la ejecución de la operación real de ordenación.

Propiedades para la ordenación

Un objeto Song hace un seguimiento de varias propiedades, como el título de la canción, el artista, el año de publicación, el nombre de archivo y un conjunto de géneros a los que pertenece la canción seleccionada por el usuario. De estas, solo las tres primeras son prácticas para ordenar. Para mayor comodidad de los desarrolladores, el ejemplo incluye la clase SortProperty, que actúa como una enumeración con valores que representan las propiedades disponibles para ordenar.

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

La clase SortProperty contiene tres constantes, TITLE , ARTIST y YEAR , cada una de las cuales almacena una cadena que contiene el nombre real de propiedad de la clase Song asociada que se puede utilizar para ordenar. En el resto del código, siempre que se indique una propiedad para ordenar, se hará con el miembro de la enumeración. Por ejemplo, en el constructor de PlayList, la lista se ordena inicialmente llamando al método sortList() de la manera siguiente:

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

Como la propiedad para ordenar se especifica como SortProperty.TITLE , las canciones se ordenan por su título.

Ordenación por propiedades y especificación de opciones de ordenación

El trabajo de ordenar la lista de canciones lo realiza la clase PlayList en el método sortList() , de la manera siguiente:

    /** 
     * 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; 
    }

Al ordenar por título o por artista, tiene sentido ordenar alfabéticamente, pero al ordenar por año, es más lógico realizar una ordenación numérica. La sentencia switch se utiliza para definir la opción de ordenación apropiada, almacenada en la variable sortOptions , según el valor especificado en el parámetro sortProperty . En este caso también se utilizan los miembros de la enumeración designados para distinguir entre propiedades, en lugar de utilizar valores especificados en el código.

Con la propiedad de ordenación y las opciones de ordenación determinadas, el conjunto _songs se ordena llamando a su método sortOn() y pasándole esos dos valores como parámetros. Se registra la propiedad de ordenación actual, ya que la lista de canciones está ordenada actualmente.

Combinación de elementos de conjunto en una cadena delimitada por caracteres

Además de utilizar un conjunto para mantener la lista de canciones de la clase PlayList, en este ejemplo también se utilizan conjuntos en la clase Song para administrar la lista de géneros a los que pertenece una canción determinada. Considérese este fragmento de la definición de la clase 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(";"); 
}

Al crear una nueva instancia de Song, se define el parámetro genres que se utiliza para especificar el género (o los géneros) al que pertenece la canción como una instancia de Array. Esto hace que sea cómodo agrupar varios géneros en una sola variable que se puede pasar al constructor. No obstante, internamente la clase Song mantiene los géneros en la variable privada _genres como una instancia de tipo String de valores separados por signos de punto y coma. El parámetro Array se convierte en una cadena de valores separados por signos de punto y coma llamando a su método join() con el valor de literal de cadena ";" como delimitador especificado.

Con este mismo símbolo, los descriptores de acceso de genres permiten establecer o recuperar géneros como un conjunto:

    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(";"); 
    }

Los descriptores de acceso set de genres se comportan exactamente igual que el constructor; aceptan un conjunto y llaman al método join() para convertirlo en una cadena de valores separados por signos de punto y coma. El descriptor de acceso get realiza la operación contraria: se llama el método split() de la variable _genres y la cadena se divide en un conjunto de valores utilizando el delimitador especificado (valor de cadena literal ";" , como antes).