Tải bản đầy đủ (.pdf) (28 trang)

Bài giảng Lập trình hướng đối tượng: Ủy thác và sự kiện

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (422.75 KB, 28 trang )

Uỷ thác và sự kiện
v 1.0 - 11/2018

Lê Viết Mẫn -

1

Uỷ thác và sự kiện


Nội dung

1. Uỷ thác
2. Sự kiện

Lê Viết Mẫn -

2

Uỷ thác và sự kiện


Uỷ thác
Delegate

Lê Viết Mẫn -

3

Uỷ thác và sự kiện



Cơ chế Uỷ thác


Muốn thực thi một phương thức nào đó của một đối tượng nào
đó nhưng người lập trình có thể chưa rõ lúc thiết kế








Dịch vụ gọi báo thức



Lúc 2h sáng, gọi số điện thoại 0905xxxxxx để tôi dậy coi đá banh

Một Button Control trong lập trình Windows Form




Khi nút được nhấn, gọi hàm Click của Form để hiển thị chữ “Hello World” lên màn hình
Ví dụ: />
Gồm 3 phần:






Hàm sẽ được gọi
Việc hàm đó sẽ làm
Sự kiện

Uỷ thác là cơ chế tạo ra các kiểu dữ liệu cho phép lưu giữ các
hàm sẽ được gọi
Lê Viết Mẫn -

4

Uỷ thác và sự kiện


Kiểu delegate





Windows API sử dụng con trỏ hàm để hỗ trợ cơ chế gọi ngược
(callback mechanism)




Một hàm gọi lại một hàm khác
Có thể xử lý các sự kiện nhấn chuột, di chuyển chuột,…


Trong .NET, delegate là một đối tượng an toàn kiểu, tham
chiếu đến một hàm khác (hoặc danh sách các hàm) mà có thể
được triệu gọi khi cần thiết
3 bước sử dụng delegate:





Định nghĩa
Tạo đối tượng kiểu delegate, đăng ký hàm xử lý
Triệu gọi

Lê Viết Mẫn -

5

Uỷ thác và sự kiện


Định nghĩa


Cú pháp khai báo nguyên mẫu hàm kèm với từ khoá delegate
public delegate int BinaryOp(int x, int y);








delegate phải giống với nguyên mẫu hàm của các hàm mà nó sẽ trỏ tới

Kiểu delegate trên có thể trỏ đến bất kỳ hàm nào nhận vào 2 số nguyên và
trả ra một số nguyên

.NET tự động tạo ra một lớp có tên là tên của delegate, và có
3 hàm: Invoke, BeginInvoke và EndInvoke

Lê Viết Mẫn -

6

Uỷ thác và sự kiện


Tạo đối tượng và triệu gọi
static int Add(int x, int y)
{
return x + y;
}

Main()

static int Subtract(int x, int y)
{
return x - y;
}

BinaryOp b = new BinaryOp(Add); // tạo đối tượng, đăng ký hàm
// triệu gọi, như gọi hàm
Console.WriteLine("10 + 10 is {0}", b(10, 10));

Lê Viết Mẫn -

7

Uỷ thác và sự kiện


Đăng ký và huỷ đăng ký


Sử dụng toán tử += để đăng ký hàm xử lý



Biến kiểu delegate có thể nhận nhiều hàm xử lý

// Danh sách chứa các hàm xử lý
BinaryOp listOfHandlers;
listOfHandlers += Add;
listOfHandlers += Subtract;



Sử dụng toán tử -= để huỷ đăng ký
listOfHandlers -= Add;


Lê Viết Mẫn -

8

Uỷ thác và sự kiện


Ví dụ - giám sát sự thay đổi dữ liệu




Viết hai lớp:



PointController - giám sát sự thay đổi dữ liệu của lớp Point. Nếu có thay



Point - gửi thông báo (triệu gọi hàm) cho lớp PointController (hoặc các
lớp khác nếu có đăng ký) thông qua kiểu delegate

đổi thì làm gì đó (ví dụ: in thông báo sự thay đổi)

Lớp Point có:






Định nghĩa kiểu delegate mới



Tại những nơi có sự thay đổi dữ liệu, triệu gọi các hàm của các lớp đã đăng ký

Khai báo biến thành phần kiểu delegate đó
Tạo hàm trợ giúp để cho phép các lớp, muốn giám sát sự thay đổi dữ liệu của
lớp Point, có thể đăng ký

Lê Viết Mẫn -

9

Uỷ thác và sự kiện


Ví dụ - giám sát sự thay đổi dữ liệu


Lớp PointController có:



Hàm xử lý khi có sự thay đổi dữ liệu, có nguyên mẫu hàm phù hợp với kiểu
delegate của lớp Point




Đăng ký hàm trên với lớp Point

Lê Viết Mẫn -

10

Uỷ thác và sự kiện


Lớp Point
class Point
{
int x;
public int X…
int y;
public int Y…
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// Khai báo kiểu delegate
public delegate void ChangedValueHandler(int newX, int newY);
// Danh sách chứa các hàm xử lý
private ChangedValueHandler listOfHandlers;
// Nơi đăng ký nhận hàm xử lý
public void RegisterWithChangedValue(ChangedValueHandler methodToCall)
{
listOfHandlers += methodToCall;
}

}

Lê Viết Mẫn -

11

Uỷ thác và sự kiện


Lớp Point
class Point
{
int x;
public int X
{
get { return x; }
set
{
x = value;
if (listOfHandlers != null)
listOfHandlers.Invoke(value, y); // Gọi hàm xử lý
}
}
int y;
public int Y…

}

Lê Viết Mẫn -


12

Uỷ thác và sự kiện


Lớp PointController
class PointController
{
Point p;
public PointController(Point p)
{
this.p = p;
// Đăng ký hàm xử lý
this.p.RegisterWithChangedValue(ChangedValueEvent);
}
// Hàm xử lý
public static void ChangedValueEvent(int newX, int newY)
{
Console.WriteLine("{0}-{1}", newX, newY);
}
}

Lê Viết Mẫn -

13

Uỷ thác và sự kiện


Lớp Program

class Program
{
static void Main(string[] args)
{
Point p = new Point(0, 0);
PointController pc = new PointController(p);
p.X = 1;
p.Y = 1;
Console.ReadKey();
}
}

Lê Viết Mẫn -

14

Uỷ thác và sự kiện


Sự kiện
Event

Lê Viết Mẫn -

15

Uỷ thác và sự kiện


Sự kiện



Ứng với mỗi thao tác người dùng sẽ có một sự kiện phát sinh,
chương trình phải đáp ứng cho mỗi sự kiện này








Dịch vụ gọi báo thức



Lúc 2h sáng, gọi số điện thoại 0905xxxxxx để tôi dậy coi đá banh

Một Button Control trong lập trình Windows Form



Khi nút được nhấn, gọi hàm Click của Form để hiển thị chữ “Hello World” lên màn hình

Sử dụng cơ chế Uỷ thác để cài đặt
Một kiểu dữ liệu đặc biệt của delegate
Khái niệm Publishing và Subcribing





Publishing - một lớp phát sinh sự kiện
Subscribing - các lớp đăng ký sẽ nhận thông báo về sự kiện phát sinh và
thực thi gì đó để đáp ứng với sự kiện

Lê Viết Mẫn -

16

Uỷ thác và sự kiện


Ba bước sử dụng event
1. Định nghĩa event
2. Đăng ký, huỷ đăng ký
3. Gửi thông báo sự kiện xảy ra

Lê Viết Mẫn -

17

Uỷ thác và sự kiện


Định nghĩa event


Hai bước:
// Vẫn khai báo kiểu delegate
public delegate void ChangedValueHandler(int newX, int newY);

// Vẫn khai báo biến event kiểu delegate trên
public event ChangedValueHandler ChangedValueEvent;





Khi khai báo biến kiểu delegate có kèm từ khoá event, trình
biên dịch sẽ tự động cung cấp:




Các hàm đăng ký và huỷ đăng ký
Các biến thành phần kiểu delegate trên (luôn là private)

Làm đơn giản đi quá trình truyền thông báo cho các đối tượng
ngoài

Lê Viết Mẫn -

18

Uỷ thác và sự kiện


Đăng ký và huỷ đăng ký
static void ChangedValue(int newX, int newY)
{
Console.WriteLine("{0}-{1}", newX, newY);

}



Sử dụng toán tử += để đăng ký
ChangedValueEvent += ChangedValue;



Sử dụng toán tử -= để huỷ đăng ký
ChangedValueEvent -= ChangedValue;

Lê Viết Mẫn -

19

Uỷ thác và sự kiện


Gửi thông báo event


Giống như gọi hàm
class Point
{
int x;
public int X
{
get { return x; }
set

{
x = value;
if (ChangedValueEvent != null)
ChangedValueEvent.Invoke(value, y);
}
}

}
hoặc
ChangedValueEvent(value, y);
Lê Viết Mẫn -

20

Uỷ thác và sự kiện


Ví dụ - giám sát sự thay đổi dữ liệu




Lớp Point có:





Định nghĩa kiểu delegate mới
Định nghĩa event mới thuộc kiểu delegate trên

Tại những nơi có sự thay đổi dữ liệu, gửi thông báo bằng cách gọi event và
truyền các tham số cần thiết

Lớp PointController có:



Hàm xử lý khi có sự thay đổi dữ liệu, có nguyên mẫu hàm phù hợp với kiểu
delegate của lớp Point



Đăng ký hàm trên với lớp Point

Lê Viết Mẫn -

21

Uỷ thác và sự kiện


Lớp Point
class Point
{
int x;
public int X
{
get { return x; }
set
{

x = value;
if (ChangedValueEvent != null)
ChangedValueEvent(value, y); // truyền thông báo
}
}
int y;
public int Y…
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// Kiểu sự kiện
public delegate void ChangedValueHandler(int newX, int newY);
public event ChangedValueHandler ChangedValueEvent;
}

Lê Viết Mẫn -

22

Uỷ thác và sự kiện


Lớp PointController
class PointController
{
Point p;
public PointController(Point p)
{

this.p = p;
p.ChangedValueEvent += ChangedValueEvent;
}
~PointController()
{
p.ChangedValueEvent -= ChangedValueEvent;
}
// Hàm xử lý sự kiện
public static void ChangedValueEvent(int newX, int newY)
{
Console.WriteLine("{0}-{1}", newX, newY);
}
}

Lê Viết Mẫn -

23

Uỷ thác và sự kiện


Lớp Program
class Program
{
static void Main(string[] args)
{
Point p = new Point(0, 0);
PointController pc = new PointController(p);
p.X = 1;
p.Y = 1;

Console.ReadKey();
}
}

Lê Viết Mẫn -

24

Uỷ thác và sự kiện


Sử dụng toán tử kiểm tra null



public int X
{
get { return x; }
set
{
x = value;
// kiểm tra khác null trước khi truyền thông báo
if (ChangedValueEvent != null)
ChangedValueEvent(value, y); // truyền thông báo
}
}

Sử dụng toán tử kiểm tra null
public int X
{

get { return x; }
set
{
x = value;
ChangedValueEvent?.Invoke(value, y);
}
}
Lê Viết Mẫn -

25

Uỷ thác và sự kiện


×