Example: PlayList. Adobe Flex, FLEX 2-PROGRAMMING ACTIONSCRIPT 3.0
إعلان
إعلان
TypedArray overridden methods
The TypedArray class overrides the four methods of the Array class that are capable of adding elements to an array. In each case, the overridden method adds a type check that prevents the addition of elements that are not the correct data type. Subsequently, each method calls the superclass version of itself.
The push() method iterates through the list of arguments with a for..in
loop and does a type check on each argument. Any argument that is not the correct type is removed from the args array with the splice() method. After the for..in
loop ends, the args array contains values only of type dataType . The superclass version of push() is then called with the updated args array, as the following code shows:
AS3 override function push(...args):uint
{ for (var i:* in args)
{ if (!(args[i] is dataType))
{ args.splice(i,1);
}
} return (super.push.apply(this, args));
}
The concat() method creates a temporary TypedArray named passArgs to store the arguments that pass the type check. This allows the reuse of the type check code that exists in the push() method. A for..in
loop iterates through the args array, and calls push() on each argument. Because passArgs is typed as TypedArray, the TypedArray version of push() is executed. The concat() method then calls its own superclass version, as the following code shows:
AS3 override function concat(...args):Array
{ var passArgs:TypedArray = new TypedArray(dataType); for (var i:* in args)
{
// type check done in push() passArgs.push(args[i]);
} return (super.concat.apply(this, passArgs));
}
Advanced Topics 247
The splice() method takes an arbitrary list of arguments, but the first two arguments always refer to an index number and the number of elements to delete. This is why the overridden splice() method does type checking only for args array elements in index positions 2 or higher. One point of interest in the code is that there appears to be a recursive call to splice() inside the for loop, but this is not a recursive call because args is of type Array rather than TypedArray, which means that the call to args.splice() is a call to the superclass version of the method. After the for..in
loop concludes, the args array contains only values of the correct type in index positions 2 or higher, and splice() calls its own superclass version, as shown in the following code:
AS3 override function splice(...args):*
{ if (args.length > 2)
{ for (var i:int=2; i< args.length; i++)
{ if (!(args[i] is dataType))
{ args.splice(i,1);
}
}
} return (super.splice.apply(this, args));
}
The unshift() method, which adds elements to the beginning of an array, also accepts an arbitrary list of arguments. The overridden unshift() method uses an algorithm very similar to that used by the push() method, as shown in the following example code:
AS3 override function unshift(...args):uint
{ for (var i:* in args)
{ if (!(args[i] is dataType))
{ args.splice(i,1);
}
} return (super.unshift.apply(this, args));
}
}
248 Working with Arrays
Example: PlayList
The PlayList example demonstrates techniques for working with arrays, in the context of a music playlist application that manages a list of songs. These techniques are:
■
■
■
■
Creating an indexed array
Adding items to an indexed array
Sorting an array of objects by different properties, using different sorting options
Converting an array to a character-delimited string
The PlayList application files can be found in the Samples/PlayList folder. The application consists of the following files:
File
PlayListApp.mxml
com/example/programmingas3/playlist/
PlayList.as
com/example/programmingas3/playlist/
Song.as
com/example/programmingas3/playlist/
SortProperty.as
Description
The main application file in MXML for Flex.
Provides the playlist functionality for the application, such as adding and sorting songs.
A value object representing information about a single song. The items that are managed by the
PlayList class are Song instances.
A pseudo-enumeration whose available values represent the properties of the Song class by which a list of Song objects can be sorted.
PlayList class overview
The PlayList class manages a set of Song objects. It has public methods with functionality for adding a song to the playlist (the addSong() method) and sorting the songs in the list (the sortList() method). In addition, the class includes a read-only accessor property, songList , which provides access to the actual set of songs in the playlist. Internally, the PlayList class keeps track of its songs using a private Array variable: public class PlayList
{ private var _songs:Array; private var _currentSort:SortProperty = null; private var _needToSort:Boolean = false;
...
}
In addition to the _songs Array variable, which is used by the PlayList class to keep track of its list of songs, two other private variables keep track of whether the list needs to be sorted
( _needToSort ) and which property the song list is sorted by at a given time ( _currentSort ).
Example: PlayList 249
As with all objects, declaring an Array instance is only half the job of creating an Array. Before accessing an Array instance’s properties or methods, it must be instantiated, which is done in the PlayList class’s constructor.
public function PlayList()
{ this._songs = new Array();
// Set the initial sorting.
this.sortList(SortProperty.TITLE);
}
The first line of the constructor instantiates the _songs variable, so that it is ready to be used.
In addition, the sortList() method is called to set the initial sort-by property.
Adding a song to the list
When a user enters a new song into the application, the code in the data entry form calls the
PlayList class’s addSong() method.
/**
* Adds a song to the playlist.
*/ public function addSong(song:Song):void
{ this._songs.push(song); this._needToSort = true;
}
Inside addSong() , the _songs array’s push() method is called, adding the Song object that was passed to addSong() as a new element in that array. With the push() method, the new element is added to the end of the array, regardless of any sorting that might have been applied previously. This means that after the push() method has been called, the list of songs is likely to no longer be sorted correctly, so the _needToSort variable is set to true . In theory, the sortList() method could be called immediately, removing the need to keep track of whether the list is sorted or not at a given time. In practice, however, there is no need for the list of songs to be sorted until immediately before it is retrieved. By deferring the sorting operation, the application doesn’t perform sorting that is unnecessary if, for example, several songs are added to the list before it is retrieved.
250 Working with Arrays
Sorting the list of songs
Because the Song instances that are managed by the playlist are complex objects, users of the application may wish to sort the playlist according to different properties, such as song title or year of publication. In the PlayList application, the task of sorting the list of songs has three parts: identifying the property by which the list should be sorted, indicating what sorting options need to be used when sorting by that property, and performing the actual sort operation.
Properties for sorting
A Song object keeps track of several properties, including song title, artist, publication year, filename, and a user-selected set of genres in which the song belongs. Of these, only the first three are practical for sorting. As a matter of convenience for developers, the example includes the SortProperty class, which acts as an enumeration with values representing the properties available for sorting.
public static const TITLE:SortProperty = new SortProperty("title"); public static const ARTIST:SortProperty = new SortProperty("artist"); public static const YEAR:SortProperty = new SortProperty("year");
The SortProperty class contain three constants, TITLE , ARTIST , and YEAR , each of which stores a String containing the actual name of the associated Song class property that can be used for sorting. Throughout the rest of the code, whenever a sort property is indicated, it is done using the enumeration member. For instance, in the PlayList constructor, the list is sorted initially by calling the sortList() method, as follows:
// Set the initial sorting.
this.sortList(SortProperty.TITLE);
Because the property for sorting is specified as SortProperty.TITLE
, the songs are sorted according to their title.
Example: PlayList 251
Sorting by property and specifying sort options
The work of actually sorting the list of songs is performed by the PlayList class in the sortList() method, as follows:
/**
* 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;
}
When sorting by title or artist, it makes sense to sort alphabetically, but when sorting by year, it’s most logical to perform a numeric sort. The switch statement is used to define the appropriate sorting option, stored in the variable sortOptions , according to the value specified in the sortProperty parameter. Here again the named enumeration members are used to distinguish between properties, rather than hard-coded values.
With the sort property and sort options determined, the _songs array is actually sorted by calling its sortOn() method, passing those two values as parameters. The current sort property is recorded, as is the fact that the song list is currently sorted.
252 Working with Arrays
تنزيل
إعلان