Override & Overload
Khám phá hai khái niệm ghi đè và nạp chồng
Khám phá hai khái niệm ghi đè và nạp chồng
Override (ghi đè) là lớp con có thể thực hiện phương thức đã có của lớp cha nhưng theo một cách khác. Method ở lớp con giống lớp cha hoàn toàn (giống cả tên lẫn tham số)
Overload (nạp chồng) là trong một lớp có thể có hai hoặc nhiều method cùng tên và khác tham số. Tuy nhiên, lớp con cũng có thể định nghĩa một overload method mới đã có ở lớp cha. Khi đó, compiler sẽ tự xác định sẽ dùng method nào dựa trên tham số truyền vào.
Tính đa hình của OOP là dựa trên hai khái niệm override và overload.
Ghi đè (override) là triển khai lại (viết lại) một phương thức đã có ở lớp cha, nhưng với một cách làm khác. Ví dụ, lớp TCha có method TienLuong (phải làm việc mới có tiền nhé, chứ không phải tự nhiên tiền lương có sẵn như field đâu) như sau:
type
TCha = class
public
function TienLuong: Integer; virtual;
end;
function TCha.TienLuong: Integer;
begin
writeln('Toi lam viec cho cong ty A 1 thang');
Result := 10000000; // 10 triệu
end;
Lớp TCon kế thừa lớp TCha, nên cũng có method TienLuong. Tuy nhiên, con có thể làm việc khác cha, nên tiền lương sẽ khác. Khi đó, phương thức TienLuong được ghi đè (override) ở lớp con.
type
TCon = class(TCha)
public
function TienLuong: Integer; override;
end;
function TCon.TienLuong: Integer;
begin
writeln('Toi lam viec cho cong ty A 1 thang');
writeln('Toi lam them gio ...');
Result := 10000000 + 500000; // Cộng thêm 500 000 đ
end;
Như vậy, nhờ có override, lớp con có thể thực hiện phương thức đã có ở lớp cha theo một cách khác.
Lưu ý: Override thì method ở lớp con phải giống với lớp cha (giống cả tên và tham số). Còn nếu khác thì dùng overload.
Để class con có thể override được method ở lớp cha, thì method ở lớp cha cần được đặt từ khóa virtual (như ví dụ trên).
Virtual thông báo cho Delphi biết rằng method này có thể được override ở lớp con.
Bên cạnh virtual, còn có một từ khóa với ý nghĩa tương đương là dynamic. Nhưng khác biệt nằm ở chỗ hai từ khóa này hoạt động:
Virtual: tối ưu hóa cho tốc độ nhanh hơn
Dynamic: tối ưu hóa cho sử dụng ít bộ nhớ hơn
Overload cho phép có hai method cùng tên nhưng khác tham số trong cùng một class. Nếu giữa class cha và class con thì không cần sử dụng overload, trình biên dịch sẽ tự xác định sử dụng method nào.
Chúng ta định nghĩa một class TCalculator với 2 method cùng tên Sum. Nhưng khác tham số: một Sum tính tổng 2 số, một Sum dùng để nối 2 chuỗi.
type
TCalculator = class
function Sum(a, b: Integer): Integer; overload;
function Sum(a, b: string): string; overload;
end;
function TCalculator.Sum(a, b: Integer): Integer;
begin
Result := a + b;
end;
function TCalculator.Sum(a, b: string): string;
begin
Result := a + b;
end;
Từ khóa overload đặt ở cuối hai method cùng tên, sau dấu chấm phẩy (;). Bên dưới phần triển khai thì không cần đặt overload.
Như vậy, tùy vào tham số mà delphi tự xác định sẽ gọi overload hàm nào.
var
Calc: TCalculator;
...
writeln(Calc.Sum(10, 5)); // Gọi Sum cho số
writeln(Calc.Sum('Viet ', 'Nam')); // Gọi Sum cho string
Từ khóa final đặt ở cuối method thông báo cho delphi biết rằng phương thức này không được phép override. Nếu cố gắng override nó, compiler sẽ báo lỗi. Ví dụ như đoạn code sau là không hợp lệ, do method TChild.ABC override phương thức TParent.ABC được đặt là final.
type
TParent = class
procedure ABC; virtual; final;
end;
TChild = class(TParent)
procedure ABC; override;
end;
Từ khóa reintroduce đặt cuối method (cuối method nhưng phải trước các từ khóa khác), cho biết rằng ở lớp con có method được override (hoặc overload) một phương thức cùng tên ở lớp cha (method ở lớp cha phải là virtual hoặc dynamic)
Nếu không sử dụng reintroduce, trình biên dịch sẽ đưa ra cảnh báo Method 'ABC' hides virtual method of base type 'TParent'.
type
TParent = class
procedure ABC; virtual;
end;
TChild = class(TParent)
procedure ABC; reintroduce;
end;
Hãy thử bỏ từ khóa reintroduce ra, và xem kết quả.