Menu

Abstract class trong PHP: abstract method, khi nào dùng

Abstract class trong PHP được khai báo bằng abstract class Name và không thể tạo instance: nó tồn tại để được kế thừa. Nó có thể chứa thuộc tính, hàm khởi tạo và các phương thức hoàn chỉnh, cùng các phương thức abstract không có thân mà mọi lớp con phải cài đặt.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

Abstract class trong PHP được khai báo bằng abstract class Name và không thể tạo bằng new. Nó làm nền cho các lớp (class) khác: có thể chứa thuộc tính, hàm khởi tạo và các phương thức hoàn chỉnh, cùng các phương thức abstract không có thân mà mọi lớp con phải cài đặt.

describe() chỉ được viết một lần trong Shape và gọi area(), phương thức do từng lớp con cung cấp. Abstract class đảm bảo phương thức đó tồn tại, nên describe() có thể dựa vào nó.

Không thể tạo abstract class bằng new

Abstract class được cố ý để dở dang: Shape::area() không có thân, nên một đối tượng Shape thuần sẽ không có gì để chạy. PHP từ chối tạo nó và ném ra Error:

Abstract method: các quy tắc

Một abstract method có chữ ký và một dấu chấm phẩy thay cho thân hàm. Mỗi lớp con phải cài đặt nó với chữ ký tương thích và phạm vi truy cập bằng hoặc rộng hơn: một phương thức abstract protected có thể trở thành protected hoặc public ở lớp con, nhưng không bao giờ là private. Một lớp chỉ cần có một abstract method là bản thân nó phải được khai báo abstract.

Một lớp con bỏ sót abstract method sẽ khiến script dừng trước khi bất kỳ dòng nào kịp chạy, trừ khi lớp con đó cũng được khai báo abstract và để phương thức lại cho các lớp con của nó:

PHP Fatal error:  Class Square contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Shape::area) in /home/index.php on line 3

Mẫu template method

Lý do phổ biến nhất để viết một abstract class: có một chuỗi bước cố định, trong đó chỉ vài bước khác nhau. Lớp cơ sở nắm giữ thứ tự các bước trong một phương thức final, còn các lớp con điền vào từng bước. Ở đây cùng một báo cáo được xuất ra dưới dạng văn bản thuần và dạng bảng HTML:

Chạy code và tab Trang hiển thị bảng HTML phía trên phiên bản văn bản thuần. open() và close() có thân mặc định, nên chỉ HtmlReport cần ghi đè chúng; row() là abstract vì không có giá trị mặc định nào hợp lý. Đặt render() là final để lớp con không thể thay đổi thứ tự các bước.

Abstract class có thể cài đặt interface

Một abstract class có thể khai báo implements và để lại một số phương thức của interface cho các lớp con. Đây là cách chuẩn để ghép một interface (kiểu) với một lớp cơ sở (phần code dùng chung):

Code khai báo kiểu bằng interface Cache, nên một lớp không thể kế thừa BaseCache (vì đã kế thừa một lớp khác) vẫn có thể cài đặt Cache trực tiếp.

Khi nào nên và không nên dùng abstract class

Hãy dùng abstract class khi các lớp trong cùng một họ dùng chung code thật sự: thuộc tính, hàm khởi tạo, các phương thức giống nhau cho tất cả. Nếu lớp cơ sở chỉ toàn abstract method, thực chất nó là một interface trá hình, và interface là lựa chọn tốt hơn vì một lớp có thể cài đặt nhiều interface nhưng chỉ kế thừa được một lớp. Nếu bạn chỉ muốn chia sẻ vài phương thức tiện ích giữa các lớp không liên quan, hãy dùng trait thay vì ép chúng chung một lớp cha.

Một phép thử nhanh trước khi viết abstract class: liệu mọi lớp con có thật sự là một loại của lớp cơ sở không (Circle là một Shape)? Nếu câu trả lời thật lòng là "nó làm được việc này" chứ không phải "nó là một trong số này", hãy viết interface.

Câu hỏi thường gặp

Abstract class trong PHP là gì?

Là một lớp được khai báo bằng abstract class Name và không thể tạo bằng new. Nó làm nền cho các lớp khác: có thể chứa thuộc tính, hàm khởi tạo và phương thức bình thường, và có thể khai báo các phương thức abstract mà mỗi lớp con phải cài đặt.

Abstract method trong PHP là gì?

Là một phương thức được khai báo với abstract và không có thân: abstract protected function render(array $rows): string;. Lớp nào chứa phương thức như vậy thì bản thân lớp đó cũng phải được khai báo abstract, và mọi lớp con không trừu tượng phải định nghĩa phương thức có chữ ký tương thích.

Abstract class trong PHP có hàm khởi tạo được không?

Được. Bạn không thể gọi new trên abstract class, nhưng hàm khởi tạo của nó vẫn chạy khi một lớp con được tạo, hoặc tự động (nếu lớp con không có hàm khởi tạo) hoặc thông qua parent::__construct(...).

Có tạo instance của abstract class trong PHP được không?

Không. new Shape() trên một abstract class sẽ ném ra Error: Cannot instantiate abstract class Shape. Thay vào đó, hãy tạo đối tượng từ một lớp con cụ thể, ví dụ new Circle(2).

Khi nào nên dùng abstract class trong PHP?

Khi nhiều lớp liên quan dùng chung code thật sự (thuộc tính, hàm khởi tạo, phương thức chung) và chỉ khác nhau ở vài bước. Đặt phần code chung vào abstract class và khai báo các bước khác nhau là abstract. Nếu không có code chung và bạn chỉ cần một bản hợp đồng, hãy dùng interface.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu