Menu

Interface trong PHP: implements, hằng số và ví dụ

Interface trong PHP liệt kê các phương thức mà một lớp cam kết phải có: interface Shape { public function area(): float; }, khi đó class Circle implements Shape bắt buộc định nghĩa area(). Tìm hiểu type hint với interface, implement nhiều interface, hằng số trong interface, interface kế thừa interface, các interface có sẵn như Countable, và so sánh interface với lớp trừu tượng.

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.

Interface trong PHP khai báo các phương thức mà một lớp cam kết cung cấp, nhưng không chứa code nào: interface Shape { public function area(): float; }. Lớp nào viết implements Shape thì phải định nghĩa area(), và mọi hàm có type hint Shape đều chấp nhận lớp đó.

describe() không biết và cũng không quan tâm nó nhận lớp nào. Hàm chỉ dựa vào lời cam kết của interface, nên một Triangle implements Shape mới vẫn chạy được với nó mà không phải sửa dòng code nào.

Lập trình theo interface

Lý do thường gặp nhất để viết interface là cho phép code phụ thuộc vào một khả năng thay vì một lớp cụ thể. Ở đây, một service đơn hàng nhận bất kỳ Notifier nào, nên cùng một đoạn code có thể gửi email khi chạy thật và gom tin nhắn lại khi chạy test:

Implement nhiều interface

Một lớp chỉ extends tối đa một lớp cha, nhưng có thể implement bao nhiêu interface tùy ý. Liệt kê chúng sau implements, cách nhau bằng dấu phẩy, rồi định nghĩa phương thức của tất cả:

JsonSerializable là một trong các interface có sẵn của PHP: implement nó cho phép bạn quyết định json_encode() tạo ra gì cho đối tượng.

Hằng số trong interface

Interface có thể khai báo hằng số. Mọi lớp implement đều kế thừa chúng, và bạn có thể đọc chúng qua tên interface hoặc tên lớp:

Trong PHP 8.3, interface không có thuộc tính, chỉ có phương thức và hằng số. Phương thức có thể là static: public static function fromArray(array $data): static; trong interface buộc mỗi lớp phải định nghĩa phương thức static đó. Với một tập giá trị cố định có liên quan với nhau, enum thường phù hợp hơn một danh sách hằng số trong interface.

Interface có thể kế thừa interface khác

Interface cũng dùng extends, và khác với lớp, chúng có thể kế thừa nhiều interface cùng lúc. Lớp implement interface con phải định nghĩa phương thức của cả chuỗi:

Interface có sẵn: Countable, IteratorAggregate, Stringable

PHP có sẵn các interface giúp đối tượng gắn vào chính ngôn ngữ. Countable giúp count($obj) hoạt động, IteratorAggregate giúp foreach hoạt động, còn Stringable được tự động implement bởi mọi lớp có phương thức __toString():

Quên một phương thức

Nếu một lớp tuyên bố implement một interface nhưng thiếu một phương thức, PHP dừng lại với lỗi nghiêm trọng nêu rõ tên phương thức bị thiếu:

Thêm phương thức total() là script chạy được. Một lớp trừu tượng được phép để trống các phương thức của interface, đó chính là lối thoát mà thông báo lỗi gợi ý.

Interface và lớp trừu tượng

Cả hai đều định nghĩa các phương thức mà một lớp phải có, và cả hai đều dùng được làm type hint. Khác biệt nằm ở những gì khác chúng có thể chứa và một lớp dùng được bao nhiêu cái:

InterfaceLớp trừu tượng
Phần thân phương thứckhông có (chỉ chữ ký)phương thức trừu tượng và hoàn chỉnh
Thuộc tínhkhôngcó
Hàm khởi tạokhai báo được, hiếm khi hữu íchcó, kèm code
Phạm vi truy cập của phương thứcchỉ publicpublic, protected, private
Hằng sốcócó
Số lượng mỗi lớpbao nhiêu cũng được (implements A, B, C)một (extends Base)
Cách dùng điển hìnhmột khả năng: Exportable, Countablecode dùng chung cho một họ lớp: Model, Controller

Hai thứ này kết hợp rất tốt: định nghĩa interface để làm type hint, và cung cấp một lớp cơ sở trừu tượng implement interface đó với phần code chung. Những lớp cần một lớp cơ sở khác vẫn có thể implement interface trực tiếp.

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

Interface trong PHP là gì?

Là một danh sách chữ ký phương thức public không có phần thân: interface Logger { public function log(string $msg): void; }. Lớp nào ghi implements Logger thì phải định nghĩa mọi phương thức trong đó, và mọi đoạn code có type hint Logger đều chấp nhận lớp đó.

Một lớp PHP có implement được nhiều interface không?

Được. Liệt kê chúng sau implements, cách nhau bằng dấu phẩy: class File implements Readable, Writable, Countable. Lớp phải định nghĩa phương thức của tất cả các interface đó. Đây là cách PHP làm được điều mà đa kế thừa làm ở các ngôn ngữ khác.

Interface và lớp trừu tượng trong PHP khác nhau thế nào?

Interface chỉ khai báo phương thức public (và hằng số); nó không có thuộc tính, không có code trong phương thức, và một lớp có thể implement nhiều interface. Lớp trừu tượng có thể chứa thuộc tính, hàm khởi tạo và phương thức hoàn chỉnh bên cạnh các phương thức trừu tượng, nhưng một lớp chỉ extends được một lớp. Dùng interface cho một khả năng ("có thể xuất dữ liệu"), dùng lớp trừu tượng cho code dùng chung trong một họ lớp.

Interface trong PHP có thuộc tính được không?

Không, trong PHP 8.3: interface có thể chứa chữ ký phương thức và hằng số (const VERSION = 2;), nhưng không có thuộc tính. Khai báo thuộc tính trong interface (property hooks) chỉ xuất hiện từ PHP 8.4.

Làm sao kiểm tra một đối tượng có implement interface trong PHP không?

Dùng instanceof: $obj instanceof Countable là true khi lớp của đối tượng implement interface đó, trực tiếp hoặc thông qua lớp cha. class_implements($obj) trả về tên mọi interface mà lớp implement.

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