Anonymous Methods
Phương thức ẩn danh
Phương thức ẩn danh
Như cái tên, phương thức ẩn danh có nghĩa là một phương thức (hàm, thủ tục) không có tên. Anonymous methods có thể gán vào một biến có cùng kiểu.
Ưu điểm của anonymous methods là có thể khai báo một hàm, thủ tục ở bất cứ nơi đâu trong chương trình, như ví dụ sau
type TFuncSum = reference to function (Num1, Num2: Integer): Integer;...var Sum: TFuncSum;begin Sum := function (Num1, Num2: Integer): Integer begin Result := Num1 + Num2; end; Write(Sum(10, 20)); // 10 + 20 = 30end.Delegate là một kiểu tham chiếu (reference to) đến hàm, thủ tục, phương thức.
Mỗi delegate đặc trưng cho cấu trúc một hàm, thủ tục hay phương thức, được xác định bằng 3 điều kiện:
Integer, Interger, String hoặc Char, Integer hoặc rỗng ()type TProcedure = reference to procedure; TSumFunction = reference to function (a, b: Integer);Các phương thức ẩn danh (phần sau) có cùng delegate thì có thể gán qua lại cho nhau.
type TFuncSum = reference to function (Num1, Num2: Integer): Integer;...var Sum: TFuncSum; Sum2: TFuncSum;begin Sum := function (Num1, Num2: Integer): Integer begin Result := Num1 + Num2; end; Write(Sum(10, 20)); // 10 + 20 = 30 Sum2 := Sum; Write(Sum2(1, 2)); // 1 + 2 = 3end.Ta thêm một biến cùng kiểu với Sum. Do hai hàm ẩn danh này có cùng kiểu (giống nhau) nên chúng có thể gán qua lại cho nhau.
Khác với các hàm, thủ tục thông thường được triển khai bên ngoài khối, hàm ẩn danh cho phép gán ngay trong một khối begin end như các ví dụ trên.
Thêm nữa, các hàm ẩn danh có thể là đối số của một hàm khác. Xem ví dụ
type TProcWriteString = reference to procedure (Str: string);...procedure RunAProc(Proc: TProcWriteString);begin WriteLn('Running ... '); Proc; WriteLn('Run complete');end;...var MyProc: TProcWriteString;begin MyProc := procedure (Str: string) begin Write(Str); end; RunAProc(MyProc);end.Như trên, ta khai báo một hàm ẩn danh (thủ tục ẩn danh) tên MyProc kiểu TProcWriteString. Sau đó triển khai nội dung cho nó bên trong cặp begin end chính.
Ta tạo thêm một hàm RunAProc (Run a procedure), nhận tham số là một biến của TProcWriteString để thực hiện.
type TFunc = reference to function (x: Integer): Integer;type TClass = class function Cong1 (x: Integer): Integer; end;...var Func: TFunc; Obj: TClass;begin Obj := TClass.Create; Func := Obj.Cong1; Write(Func(3)); // 3 + 1 = 4 Obj.Free;end.Lưu ý, ta chỉ có thể gán hàm ẩn danh cho phương thức đã được thể hiện của một class, chứ không thể gán trực tiếp cho class chưa khởi tạo.
Có nghĩa là ta cần phải thể hiện một Obj là thể hiện của Class (dùng Create như ví dụ trên). Sau đó gán Func := Obj.Cong1
Dễ thấy đoạn code sau là sai
Func := TClass.Cong1;Và phải nhớ Free object sau khi dùng xong để tránh lãng phí bộ nhớ.
Delegate có thể tạm dịch là con trỏ hàm, nó trỏ đến một hàm một thủ tục tương tự phương thức ẩn danh nhưng có những điểm khác biệt sau:
Khai báo một delegate
type TMyDelegate1 = procedure of object; TMyDelegate2 = procedure (s: string) of object; TMyDelegate3 = function : Integer of object; TMyDelegate4 = function (a, b: Integer): Boolean of object;Như trên mình khai báo 4 dạng của delegate, gồm hai loại là delegate trỏ đến thủ tục (dạng 1, 2) và trỏ đến hàm (dạng 3, 4).
Cấu trúc khai báo chung của một delegate tương tự như anonymous function nhưng không có reference of ở đầu mà thay bằng of object ở cuối.
Delegate sử dụng tương tự như phương thức ẩn danh, nhưng chỉ gán được cho method của class và không thể khởi tạo trực tiếp.