Lập trình hướng đối tượng.
Cơ chế quản lý sự kiện trong Flash.
Cú pháp
Sử dụng ActionScript là cách duy nhất để tạo ra các ứng dụng có sự tương tác người sử dụng
Biến
var x = 10.2;
var x;
Kiểu dữ liệu : int (số nguyên), number (số thập phân) string (ký tự) Boolean ( kiểu logic đúng hoặc sai)
Câu lệnh điều kiện
if (vDieuKien == true) {
doChuongTrinhA();
} else if (myValue == 2) {
doChuongTrinhB();
}
} else {
doThoat();
}
Toán tử so sánh == >, < , >=, <= … if ((vDieuKien1 == 1) && (vDieuKien2 == “KhachHang”)) { doThuTucA(); } Vòng lặp for(var i:int=0;i<10;i++) int =" 0;" int =" 0;" numb ="="" style="font-weight: bold;">Hướng đối tượng OOP- Object-Oriented Programming
Lớp (Class), Đối tượng (Object), Thuôc tinh (attribute), phương thưc (method)…..
tính bao gói, tính, kê thưa, tính đa hình ….
Đối tượng ( trạng thái (state) và hành động (behaviour) )
variable thuộc tính (attribute; property), identifier
phương thức (method)
OOP thường sử dụng hai thuật ngữ mà sau này Java cũng sử dụng là thuộc tín
(attribute) và phương thức (method) để đặc tả tương ứng cho trạng thái (state) hay biế
(variable) và hành động (behavior).
Khái niệm
+ Lập trình hướng đối tượng (OOP) là một phương pháp thiết kế và phát triển Phần mềm dựa trên kiến trúc lớp và đối tượng
+ Đối tượng (Object) là một thực thể mềm bao bọc các thuộc tính và các phương thức liên quan
+ Một đối tượng cụ thể gọi là một thể hiên ( instance)
+ Lớp (class) là một thiết kế (blueprint) hay một mẫu ban đầu (prototype) định nghĩa các thuộc tính và các phương thức chung cho tất cả các đối tượng của cùng một loại nào đó. Một đối tượng là một thể hiện cụ thể của một lớp.
+ Thuộc tính lớp (class attribute) là một hạng mục dữ liệu liên kết với một lớp cụ thể mà không liên kết với các thể hiện của lớp. Nó được định nghĩa bên trong định nghĩa lớp và được chia sẻ bởi tất cả các thể hiện của lớp.
+ Phương thức lớp (class method) là một phương thức được triệu gọi mà không tham khảo tới bất kỳ một đối tượng nào. Tất cả các phương thức lớp ảnh hưởng đến toàn bộ lớp chứ không ảnh hưởng đến một lớp riêng rẽ nào.
+ Thuộc tính (attribute) là dữ liệu trình bày các đặc điểm về một đối tượng.
+ Phương thức (method) có liên quan tới những thứ mà đối tượng có thể làm. Một phương thức đáp ứng một chức năng tác động lên dữ liệu của đối tượng (thuộc tính).
+ Một thông điệp (message) là một lời yêu cầu một hoạt động. Một thông điệp được truyền khi một đối tượng triệu gọi một hay nhiều phương thức của đối tượng khác để yêu cầu thông tin.
+ Đóng gói (encapsulation) là tiến trình che giấu việc thực thi chi tiết của một đối tượng.
+ Che giấu thông tin (information hiding) là việc ẩn đi các chi tiết của thiết kế hay thi công từ các đối tượng khác
+ Thừa kế (inheritance) nghĩa là các hành động (phương thức) và các thuộc tính được định nghĩa trong một lớp có thể được thừa kế hoặc được sử dụng lại bởi lớp khác.
+ Lớp cha (superclass) là lớp có các thuộc tính hay hành động được thừa hưởng bởi một hay nhiều lớp khác. Lớp con (subclass) là lớp thừa hưởng một vài đặc tính chung của lớp cha và thêm vào những đặc tính riêng khác.
+ Đa hình (polymorphism) nghĩa là “nhiều hình thức”, hành động cùng tên có thể được thực hiện khác nhau đối với các đối tượng các lớp khác nhau.
package {
import flash.display.Sprite;
public class Xedap extends Sprite
{
public function Xedap()
{
var maxspeed;
var xich;
}
public function start() : void
{
}
public function end() : void
{
}
}
}
Package {
Import flash.display.Sprite;
public class XedapDiaHinh extends Xedap{
public function leodoc():void{
}
}
}
public function hocdixedap(xd:Xedap):void
{
xd.start();
}
var xd : XedapDiaHinh = new XedapDiaHinh();
Ng.hocdixedap(xd);
Event - Sự kiện
Định nghĩa sự kiện.
Cơ chế làm việc của sự kiện trong Flash.
Áp dụng sự kiện trong Flash
Sự kiện là gì?
Event là lớp nằm ngay dưới lớp Object, là lớp cha của tất cả các lớp khác. Nó là lớp cơ bản
để tạo ra các đối tượng Event, là biến truyền vào trong các hàm lắng nghe sự kiện khi một
Event xảy ra.
Các thuộc tính của lớp Event mang theo những thông tin cơ bản về một Event, như là kiểu
sự kiện hoặc hành động mặc định của sự kiện có thể bị hủy bỏ hay không. Trong phần lớn
Event, những thông tin cơ bản này là rất qua n trọng. Một vài loại sự kiện khác có thể mang
theo nhiều thông tin hơn, ví dụ: Một sự kiện được phát ra khi click chuột, nó có thể mang
theo tham chiếu tới đối tượng được click, vị trí click (tọa độ x và y)...
Thêm một điều quan trọng nữa, đó là một đối tượng chỉ có thể lắng nghe sự kiện khi sự kiện đó do chính nó phát ra. Bạn có thể hỏi như vậy thì sử dụng thế nào, phần tiếp theo sẽ nói
tới điều này.
Sử dụng sự kiện như thế nào?
button.addEventListener(MouseEvent.CLICK, onClickHandler);
function onClickHandler(e: MouseEvent): void
{
trace(“bạn vừa click vào button”);
}
public function addEventListener(type:String,
listener:Function,
useCapture:Boolean = false,
priority:int = 0,
useWeakReference:Boolean = false):void
useCapture: giá trị, mặc đinh là fasle, nếu nó là true, sự kiện sẽ được xử lý ngay
trong quá trình nắm bắt của luồng sự kiện. Hãy nhớ rằng, tại giai đoạn nắm bắt,
node mục tiêu chưa được xử lý nên hàm bắt sự kiện sẽ không được gọi.
priority: mặc định là 0, nó cho biết độ ưu tiên của 1 sự kiện nếu cùng một lúc xảy
ra nhiều sự kiện, nếu tham số này càng lớn thì sự kiện có độ ưu tiên càng cao
useWeakReference: tham số này quyết định những tham chiếu tới việc lắng nghe
sự kiện này là mạnh hay yếu, mặc định là false, có Nghĩa là mạnh. Nếu
useWeakReference = false, nó sẽ ngăn ngừa việc các tham chiếu bị xóa bỏ bởi
bộ dọn rác.
Cần chú ý những gì khi làm việc với Event?
1. Mỗi đối tượng chỉ có thể nghe được một số loại Event (không kể những loại do
người dùng tự định nghĩa), tất cả đều được liệt kê trong đặc tả của lớp mà đối tượng
đó thuộc về. Nên đọc kĩ những đặc tả này trước khi làm việc.
2. Một đối tượng phát ra được Event nào thì có thể và chỉ có thể nghe được Event đó.
Thậm chí, nếu 2 đối tượng thuộc cùng 1 class cũng không thể nghe được sự kiện do
đối tượng kia phát ra
3. Nhớ removeEventListener() sau khi sử dụng, để giảm bộ nhớ mà chương trình
chiếm dụng.
4. Không nên để một đối tượng lắng nghe quá nhiều Event nếu bạn chưa thực sự hiểu
rõ về chúng. Sự thật, điều này làm chương trình của bạn chạy không ổn định.
5. Hãy tự tạo cho mình những Event riêng, điều này rất tốt vì như vậy bạn có thể kết
hợp nhiều Event có sẵn để tạo được 1 Event riêng, nó giải quyết được vấn đề mà
mục 4 nêu ra.
3.4: Bạn vẫn còn thắc mắc chứ?
Tới đây chắc bạn đã phần nào hiểu được về Event. Tôi xin được đưa ra một ví dụ cụ thể
cho các chú ý đã nêu trên
Bước 1: Tạo một file flash mới đặt tên là EventExample.fla, lưu lại. Chúng ta không cần vẽ
gì trong file này cả, tìm tới màn hình properties của stage chính, viết tên document class là
Main.
Bước 2: Tạo một file mới có tên Main.as, lưu vào cùng thư mục với file đã tạo trong bước 1.
Giờ trở lại với file EventExample.fla, ta mở cửa sổ properties ra, click vào hình cây bút chì ở
cạnh ô nhập tên document class, file Main.as sẽ được mở ra trong 1 tab mới. Chúng ta
chưa làm gì vội với file này
Bước 3: Tạo một file mới có tên NewEvent.as đặt trong cùng thư mục với 2 file đẵ tạo ở
trên, mở file này ra và viết code cho nó như sau:
package
{
import flash.events.*;
public class NewEvent extends Event
{
public static var NEW_EVENT : String = "new event";
public var index: Number = new Number();
public function NewEvent(type:String,index:int,
bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
this.index = index;
}
override public function clone():Event
{
return new NewEvent(type, this.index, bubbles,
cancelable);
}
}
}
Đoạn code trên mô tả một class được thừa kế từ Event, nó có một thuộc tính là
NEW_EVENT thuộc kiểu string và có dạng static. Điều này có nghĩa là chúng ta có thể truy
nhập vào thuộc tính này mà không cần khởi tạo một đối tượng mới thuộc kiểu NewEvent, và
thuộc tính này sẽ trở thành một Event thuộc kiểu NewEvent, nó giống với các từ khóa khi ta
sử dụng kiểu MouseEvent là CLICK hay MOUSE_UP... Biến thứ 2 là index có kiểu Number
(kiểu số tổng quát), biến này lưu một giá trị mà Event phải mang theo khi nó được phát ra.
Constructor của class này truyền vào 4 tham số:
1. Tham số thứ nhất là type, có thể thấy trong MouseEvent, chúng ta có các kiểu như:
CLICK, DOUBLE_CLICK, MOUSE_OUT, MOUSE_OVER..... đó là những kiểu event
được khai báo là các hằng static (các biến kiểu static có thể sử dụng mà không cần
khai báo đối tượng, trong đoạn code trên kiểu được khai báo là public static var
NEW_EVENT : String = "new event";)
2. Tham số thứ 2 là index, như đã nói ở trên, đây là giá trị mà Event sẽ mang theo khi
nó được phát ra, mà trước khi được phát ra thì nó phải được khởi tạo và truyền vào
một index.
3. Tham số thứ 3 là bubbles, như đã nói, khi một Event xảy ra, nó trải qua 3 giai đoạn,
nếu một Event không cần tới giai đoạn Bubbles thì thuộc tính bubbles của nó sẽ có
giá trị false, thông thường, tham số này là mặc định false, ta không cần phải quan
tâm
4. Tham số cuối cùng là cancelable, sau khi được khởi tạo, nó trở thành thuộc tính
read only, nó cho biết rằng một Event xảy ra có thể hủy bỏ được những hành động
mặc định của nó không. Ví dụ, khi ta nhập ký tự vào một ô text, sự kiện
TextEvent.TEXT_INPUT xảy ra mỗi lần ta ấn phím, hành động mặc định của nó là
hiển thị phím ta vừa ấn (nếu được). Ta hoàn toàn có thể sử dụng hàm
preventDefault() để thay đổi sự kiện mặc định đó do sự kiện TextEvent.TEXT_INPUT
có thuộc tính cancelable là true.
Sau khi nhận 4 tham số trên, constructor gọi hàm khởi tạo của cha nó là Event, rồi gán giá
trị index được truyền vào cho thuộc tính index của nó.
Sau khi khởi tạo một Event, để phát ra được Event đó thì chúng ta cần gọi tới hàm
dispatchEvent(e: Event), hàm này làm nhiệm vụ đưa một Event vào luồng sự kiện của hệ
thống. Mặt khác nó cũng gọi tới một hàm được định nghĩa trong Class Event, đó là clone().
Hàm này trả về một đối tượng Event. Thông thường chúng ta thường muốn trả về chính xác
kiểu Event chúng ta tạo ra nên hàm clone() được viết lại (như trên)
Bước 4: Tạo ra một file mới để làm đối tượng phát ra Event tại thư mục lưu chương trình.
File mới có tên là Rect.as, code của nó như sau:
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.*;
public class Rect extends MovieClip
{
private var index: int = new int();
private var mySprite: Sprite = new Sprite();
public function Rect(ind: int): void
{
this.index = ind;
this.addEventListener(MouseEvent.CLICK, onClickHandler);
mySprite.graphics.beginFill(0x001177, 1);
mySprite.graphics.drawRect(0, 0, 50, 50);
mySprite.graphics.endFill();
this.addChild(mySprite);
}
private function onClickHandler(e: MouseEvent): void
{
var evt: NewEvent = new NewEvent(NewEvent.NEW_EVENT,
this.index, false, false);
dispatchEvent(evt);
}
}
}
Class này nhằm tạo ra một đối tượng hình vuông, có thuộc tính là indexrồi cho nó lắng nghe
sự kiện click, mỗi khi đó sẽ gọi ra hàm onClickHandler(e: MouseEvent). Hàm này làm nhiệm
vụ sinh ra môt đối tượng Event thuộc kiểu NewEvent mà ta đã tạo ra trong bước 3 rồi phát
nó ra, mang theo thuộc tính index của bản thân, bạn nên nhớ thuộc tính này là private và
cũng không có hàm set/get nào khác, về lý thuyết không thể lấy được giá trị này của mỗi đối
tượng Rect.
Bước 5: Quay trở lại hàm class Main đã tạo ra trong bước 2, ta viết code cho nó như sau:
package
{
import flash.display.Sprite;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFormat;
public class Main extends Sprite
{
private var txt: TextField = new TextField();
private var arr: Array = new Array();
public function Main(): void
{
this.addChild(txt);
txt.x = 100;
txt.y = 100;
txt.width = 400;
var i:int = new int();
for (i = 1; i <= 10; i++)
{
var rect: Rect = new Rect(i);
arr.push(rect);
}
for (i = 0; i < arr.length; i++)
{
Rect(arr[i]).addEventListener(NewEvent.NEW_EVENT,
displayIndex);
this.addChild(arr[i]);
this.arr[i].x = (i * 80);
}
}
private function displayIndex (e: NewEvent): void
{
var format: TextFormat = new TextFormat("Tahoma", 20,
0xff1111);
this.txt.text = "Bạn đã click vào hình vuông thứ " +
(e.index).toString();
this.txt.setTextFormat(format);
}
}
}
Hàm này làm nhiệm vụ khởi sinh ra 10 đối tượng Rect, có index chạy từ 1 => 10, add nó lên
màn hình. Đồng thời tạo ra một text field để hiển thị. Bạn hãy chú ý lệnh
Rect(arr[i]).addEventListener(NewEvent.NEW_EVENT, displayIndex);
Lệnh này khai đăng kí để mỗi đối tượng thuộc kiểu Rect lắng nghe sự kiện NewEvent.NEW_EVENT. Hàm được gọi khi sự kiện này xảy ra là displayIndex(e: NewEvent), có
danh sách biến giống với việc bạn sử dụng những Event thông thường khác. Một lần nữa chú ý tới
lệnh
this.txt.text = "Bạn đã click vào hình vuông thứ " + (e.index).toString();
Hàm này sẽ đưa dòng chữ “bạn đã click vào hình vuông thứ i” với i = (e.index).toString(); ở đây e là biến thuộc kiểu NewEvent, nó chính là đối tượng đã được phát ra từ hàm dispatchEvent() trong class Rect. Dễ thấy, mỗi lần bạn click vào một hình vuông, một sự kiện NewEvent được phát ra, khi đó text field sẽ hiển thị index của đối tượng được click. Dưới đây là những gì bạn sẽ thấy:
Tôi đã click vào hình vuông thứ 3 và dòng chữ “Bạn đã click vào hình vuông thứ 3” xuất hiện. Vậy là,
tuy thuộc tính index của mỗi đối tượng thuộc kiểu Rect là private, nhưng chúng ta vẫn có thể lấy
được nó từ class Main.
Tới đây, bạn có lẽ sẽ thấy, ví dụ này chưa đáp ứng được những gì nêu ra trong mục 3.3, vậy thì hãy
thử thay đổi một số thứ coi. Đầu tiên thay dòng
Rect(arr[i]).addEventListener(NewEvent.NEW_EVENT, displayIndex);
Bằng:
if(i
Có nghĩa là hinh vuông thứ 10 không lắng nghe sự kiện như các hình khác. Nhưng bản than nó vẫn
tự nghe sự kiện click và phát ra sự kiện NewEvent.NEW_EVENT. Vấn đề là không hề có dòng chữ
nào hiện ra cả. Câu hỏi đặt ra: tại sao tất cả 9 đối tượng còn lại đều lắng nghe
NewEvent.NEW_EVENT, đối tượng thứ 10 phát ra sự kiện này nhưng không tự nghe, tại sao các
đối tượng khác không nghe và hiển thị thông tin index của đối tượng số 10 kia. Câu trả lời đúng như
những gì mục 3.3.1 và 3.3.2 nêu ra.
Tiếp nữa, giả sử mỗi đối tượng Rect không chỉ phải nghe sự kiện click mà còn phải nghe một vài sự
kiện khác. Rõ rang rằng nếu xử lý điều đó ở hàm Main thì sẽ rất tốn công. Thay vì thế ta xử lý việc
kiểm tra các sự kiện khác đã xảy ra chưa, nếu rồi thì phát ra Event để hàm Main nhận và xử lý. Điều
này giải quyết những gì mà mục 3.3.3 và 3.3.5 đưa ra.
Việc removeEventListener không được nêu ra ví dụ trong trường hợp này, tuy thế đây là một chú ý
không kém phần quan trọng. Các bạn hãy tham khảo bài 1 chương 4 về code trên timeline, trong đó
có sử dụng tới hàm đó, hãy đọc kĩ và thử thay đổi để không sử dụng lệnh đó nữa, bạn sẽ thấy một số
bất ổn.
Trước khi kết thúc, cảm ơn vì bạn đã theo dõi tới đây….