Class & object
Tìm hiểu về hai thành phần quan trọng nhất trong lập trình hướng đối tượng
Tìm hiểu về hai thành phần quan trọng nhất trong lập trình hướng đối tượng
Bài này mình sẽ trình bày về các thành phần cơ bản của một class thông qua ví dụ. Bạn có thể xem và nắm được cấu trúc, cách khai báo của class thông qua ví dụ bên dưới.
Chúng ta hãy lấy ví dụ về class gần gũi nhất, con người. Đoạn code dưới đây miêu tả một class TConNguoi (tên class thường đặt có chữ cái T ở đầu)
Class được khai báo sau từ khóa type.
type
TConNguoi = class
var
Ten: string;
Tuoi: Byte;
public
procedure AnUong;
function SuyNghi: string;
published
property HoiTen: string read Ten;
end;
Một class như trên gồm 3 thành phần cơ bản:
Trường (field): Là các biến bên trong class (Ten, Tuoi). Các biến này có thể có từ khóa var hoặc không đều được
Phương thức (method): Là các hàm, thủ tục bên trong class (AnUong, SuyNghi).
Thuộc tính (property): Giống như trường, nhưng có khả năng quản lý cao hơn (property trong ví dụ trên là HoiTen)
Lưu ý: Từ đây, các field, method, property của class mình sẽ viết dưới dạng Tên class . Tên, ví dụ property HoiTen sẽ được viết là TConNguoi.HoiTen, điều này sẽ giúp bạn xác định rõ hơn property thuộc class nào.
Umm, ... bây giờ đến phần triển khai nội dung cho class. Như các bạn thấy ở trên, các method (AnUong, SuyNghi) chưa có phần thân (nội dung) mà chỉ có phần đầu thôi.
Trong phần triển khai class, chúng ta phải viết thêm các mã lệnh cho method đã khai báo. Lưu ý, phần triển khai phải đặt bên ngoài class nhé.
procedure TConNguoi.AnUong;
begin
writeln('Toi dang an ...');
writeln('Toi da an xong !');
end;
function TConNguoi.SuyNghi: string;
begin
Result := 'Toi dang suy nghi mot so thu ...';
end;
Về cơ bản thì triển khai class (class implement) giống như viết lại các hàm, thủ tục thôi. Nhưng chú ý đến phần đầu của hàm, thủ tục. Có thêm tên class và dấu chấm (.) nữa đúng không ?
Điều đó cho biết rằng, hàm, thủ tục này là method của class.
Chúng ta không thể sử dụng trực tiếp class được (vì class chỉ là một loại đối tượng, không phải là đối tượng cụ thể). Như vậy, đoạn code sau là sai.
TConNguoi.AnUong;
Để sử dụng class, cần biến class thành object. Quá trình này gọi là thực thể hóa (instantiation) từ class thành object. Khi đó, object là thực thể (instance) được tạo ra từ class. Một class có thể tạo ra nhiều object khác nhau.
Trong delphi, sử dụng hàm tạo (constructor) của class để thực thể hóa ọbject như sau
var
OngA: TConNguoi;
begin
OngA := TConNguoi.Create;
try
OngA.AnUong;
finally
OngA.Free;
end;
end;
Như thế, thông qua object (OngA - ông A), ta có thể thực hiện mọi thứ y như class.
Có thể xem class như kiểu dữ liệu, còn object như biến. Chúng ta có thể làm việc với biến, nhưng kiểu dữ liệu thì không.
Lưu ý: Sử dụng cấu trúc try ... finally để quản lý object được tạo ra. Khi tạo object bằng Create, cần chú ý phải hủy nó đi bằng Free như trên để tránh lãng phí bộ nhớ (Ông A mà không chết đi thì sẽ có rất nhiều người sinh ra > Trái Đất hết chỗ > Chết hết > Chương trình bị dừng :D). Xem thêm về quản lý bộ nhớ.
Nâng cao: Thực tế, có thể sử dụng class trực tiếp mà không cần object. Class như thế gọi là static class (lớp tĩnh) hoặc là phương thức được gọi là static method (phương thức tĩnh). Vấn đề này sẽ được bàn sau.
Các phần bên trong object (field, property, method) có thể được truy cập (gọi) đến theo cú pháp Tên object . Tên field / method / property.
OngA.AnUong;
writeln(OngA.Tuoi);
Đối với các class lồng nhau, thì bạn sử dụng nhiều dấu chấm liên tiếp như sau.
OngA.ConThuNhat.AnUong;
writeln(OngA.ConThuHai.Ten);
Như trên, OngA là một object, bên trong ông A có một object khác là ConThuNhat và ConThuHai. Hai object con này có các method, field, property khác nữa.
Các class trong Delphi tổ chức theo dạng phân cấp (giống như phả hệ), từ một class tổ tiên chung là TObject phân nhánh ra các class con, từ các class con này lại phân nhánh ra các class nhỏ hơn khác. Tất cả hợp lại thành hệ thống các class.
Class chứa các class con là lớp cha (parent class) hoặc lớp cơ sở (base class). Lớp con được gọi là subclass.
Ví dụ sau là ba class, hình học (các hình nói chung), hình vuông và hình tròn. Dễ thấy, hình vuông và hình tròn đều từ hình mà ra. Suy ra, hình là parentclass, hình vuông và hình tròn là subclass.
Đoạn code dưới đây mô tả 3 class trên.
type
THinh = class
end;
THinhVuong = class(THinh) // Khai báo kế thừa từ THinh
Canh: Integer;
end;
THinhTron = class(THinh) // Lớp cha là THinh
BanKinh: Integer;
end;
Như vậy, bạn có thể thấy, lớp con kế thừa từ lớp cha, nhưng cũng có thể thêm những thứ mới, Canh của THinhVuong hoặc BanKinh của THinhTron cho phù hợp.