Chương 3 ActionScript
3.2. Các thành phần cơ bản trong ActionScript
3.2.1. Lớp và đối tượng
Bước đầu tiên để viết một chương trình là xác định những lớp của nó. Một số lớp
trong chương trình được viết bởi người dùng để thực hiện một số thao tách riêng biệt (custom classes), một số khác được cung cấp bởi ActionScript và các chế độ
vụ cơ bản như thao tác với số và văn bản, nghe âm thanh, thể hiện hình ảnh, kết nối mạng và đáp ứng các yêu cầu của người dùng.
Từ những lớp trong chương trình, chúng ta tạo được những đối tượng và ra lệnh cho chúng thực hiện cơng việc.
Một nhóm lớp quan trọng được xây dựng trực tiếp từ ActionScript gọi là lớp tự
nhiên - Native classes dùng để thao tác các loại thông tin căn bản như là số và văn bản.
Native classes của ActionScript
Lớp Mô tả
String Kiểu chuỗi
Boolean Kiểu logic đúng hoặc sai Number Kiểu số có dấu chấm động Int Kiểu số nguyên
Uint Kiểu số nguyên dương Array Kiểu mảng
Error Kiểu lỗi chương trình Date Kiểu ngày tháng
Math Bao gồm các giá trị tốn học thơng thường và các hàm RegExp Định nghĩa cơng cụ tìm kiếm và thay thế văn bản
Function Thể hiện một tập hợp các lệnh được thi hành hoặc gọi nhiều lần
Object Định nghĩa các tính năng cơ bản của mọi đối tượng trong ActionScript
Bảng 5: Các lớp tự nhiên của ActionScript
Chương trình ActionScript được tạo bởi nhiều lớp. Mỗi lớp được đặt tên, có đặc
trưng và một vai trị trong chương trình lớn. Để bắt đầu một chương trình, Flash tự
động tạo một lớp chính - main class cho chương trình.
3.2.2. Packages
Package là một nhóm các lớp. Mỗi package phân định một vùng độc lập của chương trình.
Tên của package phải bắt đầu bằng ký tự viết thường. Trong khi tên lớp thường bắt
đầu bằng ký tự viết hoa. Điều này giúp chúng ta dễ dàng phân biệt tên lớp và tên
package.
Tên của package sẽ được tự động gán cho 1 phần trong tên lớp thuộc package đó.
Ví dụ như lớp Player thuộc package game sẽ có tên là game.Player
Định nghĩa một package:
package packageName{ ...}
Một package muốn sử dụng những lớp public của package khác thì phải import.
Import packageName.*
3.2.3. Hàm và biến
Để định nghĩa một hàm ta dùng function Để định nghĩa một biến ta dùng var
Ví dụ :
package vuonThu {
public class VuonThuAo {
public function VuonThuAo ( ) { var thu = new ThuAo;
} } }
3.2.3.1. Biến
Biến có thể được khai báo là public, internal, protected hoặc private.
Thuộc tính Truy xuất biến trong
Public Internal Protected Private
Lớp chứa định nghĩa biến Cho phép Cho phép Cho phép Cho phép Lớp kế thừa của lớp chứa
định nghĩa biến
Cho phép Cho phép Cho phép Không cho phép
Khác lớp nhưng cùng một package
Cho phép Cho phép Không cho phép
Không cho phép
Không thuộc cùng một package
Cho phép Không cho phép
Không cho phép
Không cho phép
Bảng 6: Điều khiển truy xuất biến
3.2.3.2. Hàm
Điều khiển truy xuất hàm:
Thuộc tính Public Internal Hàm trong cùng một package Cho phép Cho phép Hàm không thuộc cùng một package
Cho phép Không cho phép
Bảng 7: Điều khiển truy xuất hàm
Nếu hàm không được định nghĩa là public hay internal thì ActionScript mặc định hiểu là internal.
3.2.3.2.1. Hàm toàn cục
Một hàm được định nghĩa tại một package khơng tên gọi là hàm tồn cục. Hàm này có thể sử dụng trong tồn chương trình mà khơng cần import.
Ví dụ:
import flash.system.*; public function isLinux ( ) { return Capabilities.os == "Linux"; }
package setup {
public class Welcome {
public function Welcome ( ) { if (isLinux( )) {
… }}}}
isLinux() được sử dụng trong package setup mà không cần import
3.2.3.2.2. Hàm lồng Ví dụ: public function a ( ) { b( ); function b ( ) { … } }
Hàm b() chỉ được sử dụng bên trong hàm a(). Bên ngồi hàm a() khơng thể gọi hàm b()
3.2.3.2.3. Hàm ở cấp ngoài cùng
Trong một file A.as, khi một hàm được định nghĩa ngồi cùng, khơng thuộc bất kỳ một package nào thì nó có thể được sử dụng ở bất kỳ đâu trong A.as. Và hàm này
khơng được khai báo internal hay public. Ví dụ:
function f ( ) { }
//Có thể dùng f() ở đây class A { //Có thể dùng f() ở đây public function A ( ) { //Có thể dùng f() ở đây } } } //Có thể dùng f() ở đây
3.2.3.2.4. Hàm được gán cho một biến
function a ( ) { }
var b = a;
Kết quả trả về của hàm a() được gán cho biến b. Khi gán var b = a(), dấu ngoặc ()
được lượt bỏ.
3.2.3.2.5. Truyền tham số trong hàm
function (param1, param2, ...paramn) {
}
Khi biến được gán
var someVariable = function (param1, param2, ...paramn) thì hàm có thể được sử dụng thong qua biến
someVariable(arg1, arg2, ...argn)
3.2.3.2.6. Hàm đệ quy Hàm gọi lại chính nó Ví dụ: function trouble ( ) { trouble( ); }
Hàm tính giai thừa sử dụng đệ quy function factorial (n) { if (n < 0) { return; } else if (n <= 1) { return 1; } else { return n * factorial(n-1); } } factorial(3); // Giá trị trả về: 6 factorial(5); // Giá trị trả về: 120 3.3. Sự kiện và xử lý sự kiện
Trong ActionScript, sự kiện được chia làm hai loại:
• Sự kiện được thiết lập sẵn (built-in event): mô tả những thay đổi trạng thái trong mơi trường thực thi. Ví dụ như sự kiện click chuột.
• Sự kiện tự định nghĩa (custom event): mô tả những thay đổi trạng thái của chương trình. Ví dụ như sự kiện kết thúc game.
Các sự kiện rất thường gặp trong ActionScript. Trong thực tế, một chương trình thuần ActionScript, sau khi hàm main được thực thi thì tất cả những mã sau đó đều
được thi hành bằng sự kiện. Vì vậy, ActionScript cung cấp cấu trúc sự kiện rất dồi
dào, phong phú làm cơ sở cho cả built-in event và custom event
3.3.1. Sự kiện ActionScript cơ bản
Xử lý sự kiện trong ActionScript chúng ta dùng event listeners. Event listeners là một hàm hoặc một phương thức được thực thi khi một sự kiện được gọi. Nó đợi,
được gọi, ActionScript gọi thực thi tất cả các event listeners nào đã được đăng ký
với sự kiện đó. Quy trình thơng báo như vậy gọi là việc gửi sự kiện (event
dispatch).
Khi việc gửi sự kiện bắt đầu, ActionScript tạo một đối tượng gọi là đối tượng sự
kiện (event object) thay mặt cho sự kiện đó. Đối tượng sự kiện luôn luôn là một thể hiện của lớp sự kiện.
Việc gửi sự kiện trong ActionScript có sự kiện đích (event target) ln ln gắn liền với sự kiện.
Để phản hồi sự kiện được gửi đến, phương thức đăng ký sự kiện chỉ đơn giản đăng
ký với event target. Theo đó, tất cả các đối tượng event target đều là những thể hiện của lớp kế thừa từ lớp EventDispatcher hoặc lớp thực thi interfaces IEventDispatcher.
Lớp EventDispatcher cung cấp các phương thức đăng ký hoặc hủy đăng ký một
phương thức đăng ký sự kiện : addEventListener( ) and removeEventListener( )…
3.3.2. Đăng ký một phương thức đăng ký sự kiện -
Event listener
Gồm 5 bước:
1. Quyết định tên gọi loại sự kiện.
Flash cung cấp nhiều loại sự kiện đã được định nghĩa sẵn. Tên của mỗi loại sự kiện
được truy xuất thông qua các hằng số của lớp sự kiện hoặc một trong các đại diện
của nó. Ví dụ như hằng số của loại sự kiện kết thức hàm Event.COMPLETE có giá trị là “complete”
Ví dụ:
complete event
Event object type: flash.events.Event
Event.type property = flash.events.Event.COMPLETE
Event.type property cho ta biết hằng số cho sự kiện “complete” là
flash.events.Event.COMPLETE
Mặt khác, để phản hồi loại sự kiện được gọi, đầu tiên chúng ta phải tìm được hằng số đại diện cho nó.
2. Quyết định kiểu dữ liệu của đối tượng sự kiện tượng trưng cho sự kiện đó. Ví dụ:
complete event
Event object type: flash.events.Event
Event.type property = flash.events.Event.COMPLETE
theURLLoader.addEventListener(Event.COMPLETE, someListener);
Event object type cho ta biết kiểu dữ liệu của đối tượng Event.COMPLETE là
flash.events.Event
3. Tạo một phương thức đăng ký sự kiện để phản hồi cho sự kiện. Phương thức
đăng ký sự kiện phải được định nghĩa là tham số có cùng kiểu dữ liệu với đối
tượng sự kiện ở bước 2. Ví dụ:
private function completeListener (e: flash.events.Event):void { trace("Load complete");
}
Tất cả phương thức đăng ký sự kiện đều có kiểu trả về là void.
Phương thức đăng ký sự kiện là phương thức thường được khai báo private nên
không thể truy xuất từ lớp khác.
4. Sử dụng phương thức addEventListener() của lớp EventDispatcher để đăng
ký phương thức đăng ký sự kiện với event target.
complete event
Event object type: flash.events.Event
Event.type property = flash.events.Event.COMPLETE
someListener() sẽ đăng ký phương thức đăng ký sự kiện với event target
theURLLoader cho sự kiện Event.COMPLETE
Tham số đầu tiên của addEventListener() là tên của loại sự kiện, tham số thứ hai là một tham chiếu cho phương thức đăng ký sự kiện.
Đây là dạng đầy đủ của phương thức addEventListener():
addEventListener(type, listener, useCapture, priority, useWeakReference) Hai tham số đầu tiên là bắt buộc.
5. Đợi sự kiện xảy ra
Chúng ta đã khởi tạo một phương thức đăng ký sự kiện cho Event.COMPLETE và
đăng ký nó với event target. Gọi thực thi someListener():
theURLLoader.load (new URLRequest(“someFile.txt”));
Khi đã load xong someFile.txt, ActionScript gửi đi sự kiện Event.COMPLETE đã
đăng ký, và someListener() được thực thi.
Sau là một ví dụ đầy đủ về 5 bước: package {
import flash.display.*; import flash.net.*; import flash.events.*;
public class FileLoader extends Sprite { public function FileLoader ( ) {
// Tạo đối tượng sự kiện đích
var urlLoader:URLLoader = new URLLoader( ); // Đăng ký phương thức đăng ký sự kiện
urlLoader.addEventListener(Event.COMPLETE, completeListener); // Gọi hàm để kích hoạt sự kiện xảy ra
urlLoader.load(new URLRequest("someFile.txt")); }
private function completeListener (e:Event):void { trace("Load complete");
} } }
3.3.3. Hủy đăng ký một phương thức đăng ký sự kiện
- Event listener
Sử dụng phương thức removeEventListener() của lớp EventDispatcher
eventTarget.removeEventListener(type, listener, useCapture)
Ví dụ:
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener);
Để tiết kiệm bộ nhớ, event listeners phải được hủy nếu nó khơng cần dùng đến
trong chương trình.
3.3.4. Đối tượng Target
Trong mọi việc gửi sự kiện, đối tượng sự kiện truyền cho các phương thức đăng ký sự kiện sẽ định nghĩa một biến target tham chiếu đến đối tượng target.
public function someListener (e:SomeEvent):void { trace(e.target);
}
3.3.5. Quyền ưu tiên đối với phương thức đăng ký sự
kiện - Event Listener
Khi nhiều event listener được đăng ký cho một loại sự kiện của một đối tượng nào
đó thì cái nào đăng ký trước sẽ được ưu tiên. Ví dụ như có 2 event listener:
completeListenerA() và completeListenerB(). Khi sự kiện Event.COMPLETE được gọi thì completeListenerA() sẽ thực thi trước vì nó được đăng ký trước.
Ví dụ:
import flash.display.*; import flash.net.*; import flash.events.*;
public class FileLoader extends Sprite { public function FileLoader ( ) {
var urlLoader:URLLoader = new URLLoader( );
urlLoader.addEventListener(Event.COMPLETE, completeListenerA); urlLoader.addEventListener(Event.COMPLETE, completeListenerB); urlLoader.load(new URLRequest("someFile.txt"));
}
private function completeListenerA (e:Event):void { trace("Listener A: Load complete");
}
private function completeListenerB (e:Event):void{ trace("Listener B: Load complete");
} } }
Để thay đổi thứ tự mặc định xảy ra của event listeners, ta có thể dùng tham số
priority của phương thức addEventListener()
addEventListener(type, listener, useCapture, priority, useWeakReference)
Tham số priority là số nguyên nếu khơng được xác định thì nó được mặc định là 0.
3.4. ActionScript động
ActionScript rất độc đáo khi cho phép sửa đổi cấu trúc của tất cả các lớp, thậm chí là của các đối tượng riêng lẻ trong lúc thực thi. Ví dụ như trong lúc thực thi, một chương trình có thể:
• Thêm những phương thức mới hoặc những biến mới vào bất kỳ đối tượng đơn, đặc biệt nào.
• Tạo một lớp mới trọn vẹn từ đầu.
• Thay đổi lớp cha của một lớp.
3.4.1. Biến động
Biến động chỉ được thêm vào lớp động (lớp được khai báo với thuộc tính dynamic). Lớp con của lớp động cũng không được xem là động nếu định nghĩa của nó khơng có thuộc tính dynamic.
Ví dụ:
dynamic public class Person { }
// Lớp Person không định nghĩa biến eyeColor. var person:Person = new Person( );
person.eyeColor = "brown";
Ta định nghĩa lớp Person là dynamic nên ta có thể thêm một biến mới eyeColor vào
đối tượng Person mặc dù lớp Person không định nghĩa biến eyeColor.
Nếu ta định nghĩa kiểu dữ liệu khi tạo biến eyeColor: person.eyeColor:String = "brown";
thì sẽ bị báo lỗi là: “Error! :String is not allowed here”
3.4.2. Tự động thêm hành vi mới cho một thể hiện
Cú pháp như sau:
someObject.someDynamicVariable = someFunction;
hoặc
someObject.someDynamicVariable = function (param1, param2, ...paramn) {
}
someObject là tên một thể hiện của một lớp động.
Ví dụ:
var info:Object = new Object( ); info.city = "Toronto";
info.country = "Canada";
info.getAddress = function ( ):String { return this.city + ", " + this.country; }
trace(info.getAddress( ));
3.4.3. Tham chiếu động cho biến và phương thức
Cú pháp:
someObject[someExpression]
someObject là một tham chiếu đến đối tượng mà biến của nó truy xuất đến. someExpression là tên biến.
Ví dụ:
var info:Object = new Object( ); info["city"] = "Toronto";
hoặc:
var detail:String = "city";
trace(info[detail]); // Xuất ra màn hình: Toronto
Chú ý trong trường hợp nếu ta đặt tên biến là số thì trong dấu [] vẫn được chấp nhận var info:Object = new Object( );
info["411"] = "Information Line";
Nhưng khi khởi tạo biến bằng toán tử (.) thì sẽ bị báo lỗi var info:Object = new Object( );
info.411 = "Information Line"; // Thông báo lỗi: Identifiers must not start with a number
3.5. XML và E4X
Từ Flash Player 5, ActionScript (AS) đã có cơng cụ làm việc với XML. Ở AS 1.0 và 2.0 dữ liệu XML được tạo ra và xử lý bằng biến và hàm của lớp XML được xây dựng sẵn. Lớp XML dựa trên W3C DOM, một chuẩn giao tiếp với XML.
Ở AS 3.0 bộ công cụ để làm việc với XML đã được nâng cấp hoàn toàn. AS 3.0
triển khai ECMAScript cho XML (E4X), một ngôn ngữ chính thức làm việc với XML như một kiểu dữ liệu cơ bản. E4X rất tiện dụng và linh hoạt để làm việc với XML.
3.5.1. Dữ liệu phân cấp XML
Chúng ta xem XML như là một dữ liệu phân cấp. Nếu xem dữ liệu XML như là một cây phân cấp thì trong đó những thành phần được xem là những nút (node) trên cây. Xét ví dụ (1) đoạn dữ liệu XML sau:
<SACH ISBN=”1231456”>
<TUA>Mat Ma DaVinci</TUA> <TACGIA>Dan Brown</TACGIA>
<NHA XUAT BAN>VHTT</NHA XUAT BAN> </SACH>
Các thành phần <SACH>, <TUA>, <TACGIA>, <NHA XUAT BAN> và các chuỗi “Mat Ma DaVinci”, “Dan Brown”, “VHTT” được xem là các nút (node) trên cây. Thành phần <SACH> là gốc của cây hay nút gốc của dữ liệu XML. Các nút <TUA>, <TACGIA>, <NHA XUAT BAN> là thành phần con của <SACH>. <TUA>, <TACGIA>, <NHA XUAT BAN> là các thành phần anh em của nhau. Các thành phần <TUA>, <TACGIA>, <NHA XUAT BAN> có một nút con văn bản lần lượt là “Mat Ma DaVinci”, “Dan Brown”, “VHTT”. Các nút văn bản này là nút cuối cùng trên cây.
3.5.1.1. Biểu diễn dữ liệu XML trong E4X
Trong E4X dữ liệu XML được biểu diễn bằng một trong hai kiểu dữ liệu cơ bản của AS là XML và XMLList và những lớp tương ứng của chúng cũng được đặt tên là
XML và XMLList, nếu một thành phần XML có các thành phần con (như con của <SACH> là <TUA>) hoặc có các nút con văn bản (như con của <TUA> là “Mat Ma DaVinci”) thì những thành phần con này được gói trong XMLList bởi một thể hiện của cha chúng. Các nút con của một thành phần XML ln được gói trong một XMLList, thậm chí thành phần đó chỉ có duy nhất một con. Nếu một thành phần
XML có các thuộc tính, chú thích, câu lệnh thì chúng cũng được gói trong
XMLList. Tuy nhiên chú thích và các câu lệnh theo mặc định bị loại bỏ bởi E4X. Xét lại đoạn ví dụ:
<SACH ISBN=”1231456”>
<TUA>Mat Ma DaVinci</TUA> <TACGIA>Dan Brown</TACGIA>
<NHA XUAT BAN>VHTT</NHA XUAT BAN> </SACH>
Thành phần <SACH> được giữ bởi một thể hiện của XML. Thể hiện này chứa 2 thể hiện XMLList, một cho các thuộc tính của <SACH>, cái cịn lại cho các thành phần con của nó. Thành phần <SACH> có duy nhất một thuộc tính do đó XMLList cho thuộc tính <SACH> chứa duy nhất một thể hiện (ISBN). XMLList cho các thành phần con của <SACH> chứa 3 thể hiện là <TUA>, <TACGIA>, <NHA XUAT BAN>. Mỗi một thể hiện XML có một XMLList gồm duy nhất một thể hiện XML lần lượt là “Mat Ma DaVinci”, “Dan Brown”, “VHTT”.
3.5.1.2. Tạo dữ liệu XML với E4X