Ghi đè phương thức
Thuộc phần Lập trình hướng đối tượng trong hành trình PHP của Coddy. Bài học 23 trên 91.
Đôi khi, phương thức kế thừa từ lớp cha không phù hợp với nhu cầu của lớp con. Ghi đè phương thức cho phép lớp con cung cấp cách triển khai riêng cho một phương thức đã có trong lớp cha.
Để ghi đè một phương thức, bạn chỉ cần định nghĩa một phương thức trong lớp con có cùng tên với phương thức của lớp cha:
<?php
class Animal {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function speak() {
return "$this->name makes a sound";
}
}
class Cat extends Animal {
public function speak() {
return "$this->name says meow";
}
}
$cat = new Cat("Whiskers");
echo $cat->speak();
Đầu ra:
Whiskers says meowLớp Cat thay thế hoàn toàn phương thức speak() của lớp cha bằng phiên bản riêng. Khi bạn gọi speak() trên một đối tượng mèo, PHP dùng phần triển khai của lớp con.
Bạn cũng có thể mở rộng hành vi của lớp cha bằng cách kết hợp parent:: với logic riêng:
<?php
class Dog extends Animal {
public function speak() {
return parent::speak() . " - woof woof!";
}
}
$dog = new Dog("Rex");
echo $dog->speak();
Đầu ra:
Rex makes a sound - woof woof!Điểm chính: Ghi đè phương thức cho phép các lớp con tùy chỉnh hành vi được kế thừa. Bạn có thể thay thế hoàn toàn một phương thức hoặc dùng parent:: để bổ sung cho phần triển khai ban đầu.
Thử thách
DễHãy xây dựng một hệ thống thông báo để tìm hiểu cách lớp con có thể thay thế hoàn toàn hoặc mở rộng phương thức của lớp cha thông qua việc ghi đè phương thức.
Bạn sẽ tạo ba tệp phối hợp với nhau để gửi các loại thông báo khác nhau, mỗi loại có cách hoạt động riêng:
Notification.php: Định nghĩa lớpNotificationlàm lớp cơ sở cho mọi loại thông báo. Lớp này cần có thuộc tính công khai$recipientvà một hàm khởi tạo nhận rồi gán người nhận. Thêm phương thứcsend($message)trả về"Sending to [recipient]: [message]".UrgentNotification.php: Định nghĩa lớpUrgentNotificationkế thừa từNotification. Thêm tệp Notification ở đầu tệp. Lớp này cần ghi đè hoàn toàn phương thứcsend($message)để trả về"URGENT to [recipient]: [message]!!!": chú ý tiền tố "URGENT" và các dấu chấm than ở cuối. Đây là ví dụ về việc thay thế hoàn toàn cách hoạt động của lớp cha.LoggedNotification.php: Định nghĩa lớpLoggedNotificationkế thừa từNotification. Thêm tệp Notification ở đầu tệp. Lớp này cần ghi đèsend($message)nhưng vẫn dựa trên phần triển khai của lớp cha: gọiparent::send($message)rồi thêm" [logged]"vào kết quả. Đây là ví dụ về việc mở rộng thay vì thay thế cách hoạt động.
Trong main.php, thêm cả ba tệp lớp thông báo. Bạn sẽ nhận hai đầu vào: tên người nhận và thông điệp cần gửi. Tạo một đối tượng cho mỗi loại thông báo, tất cả cùng dùng một người nhận, rồi gọi send() với thông điệp trên từng đối tượng. In mỗi kết quả trên một dòng riêng theo thứ tự sau: thông báo thông thường, thông báo khẩn cấp, rồi thông báo đã ghi nhật ký.
Thử thách này minh họa cả hai cách ghi đè phương thức: UrgentNotification thay thế hoàn toàn logic của lớp cha bằng cách định dạng riêng, còn LoggedNotification dùng parent:: để giữ cách hoạt động ban đầu và bổ sung thêm.
Tự làm thử
<?php
require_once 'Notification.php';
require_once 'UrgentNotification.php';
require_once 'LoggedNotification.php';
// Đọc đầu vào
$recipient = trim(fgets(STDIN));
$message = trim(fgets(STDIN));
// TODO: Tạo một instance cho mỗi loại thông báo (tất cả dùng cùng một người nhận)
// TODO: Gọi send() với nội dung thông báo trên từng instance
// In mỗi kết quả trên một dòng riêng theo thứ tự sau:
// 1. Thông báo thông thường
// 2. Thông báo khẩn cấp
// 3. Thông báo có ghi nhật ký
?>Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về OOP
Tệp bên ngoàiGiới thiệu về OOPLớp và đối tượngTừ khóa $thisPhương thứcThuộc tínhHàm khởi tạo (__construct)Hàm hủy (__destruct)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnTừ khóa parent::Ghi đè phương thứcTừ khóa finalLớp trừu tượngÔn tập: hệ thống phân cấp nhân viên7Đóng gói
Công khai, được bảo vệ, riêng tưTìm hiểu sâu về bộ điều chỉnh quyền truy cậpGetter và setterẨn thông tinRút gọn hàm khởi tạo (8.0)Ôn tập: hệ thống hồ sơ học sinh2Không gian tên và tự động nạp
Giới thiệu về không gian tênTừ khóa useChuẩn tự động nạp PSR-4Trình tự động nạp của ComposerÔn tập: dự án có tổ chức5Giao diện và hợp đồng
Giới thiệu về giao diệnTriển khai giao diệnTriển khai nhiều giao diệnGiao diện và lớp trừu tượngGợi ý kiểu với giao diệnÔn tập: Máy tính hình học8Phương thức ma thuật
Giới thiệu về phương thức ma thuật__toString và __debugInfo__get, __set, __isset, __unset__call và __callStatic__clone và sao chép đối tượng__serialize và __unserializeÔn tập: Bộ sưu tập tùy chỉnh3Thuộc tính của lớp
Thuộc tính instance và staticHằng số trong lớpPhương thức và thuộc tính staticThuộc tính private và protectedThuộc tính chỉ đọc (PHP 8.1)Ôn tập: Trình quản lý tài khoản ngân hàng6Đa hình
Xem lại việc ghi đè phương thứcĐa hình qua giao diệnGợi ý kiểu và kiểu hợpLiên kết tĩnh muộnÔn tập: bộ xử lý thanh toánTự luyện tập: Trình biên dịch PHP online