Xem lại việc 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 33 trên 91.
Bạn đã học về việc ghi đè phương thức trong chương Kế thừa. Giờ hãy cùng khám phá mối liên hệ giữa khái niệm này với tính đa hình, một trong những khái niệm mạnh mẽ nhất trong lập trình hướng đối tượng.
Đa hình (polymorphism) nghĩa là “nhiều hình thức”. Khi ghi đè một phương thức (method) trong lớp con (child class), bạn tạo cho phương thức đó một hình thức khác nhưng vẫn giữ nguyên tên. Điều kỳ diệu xảy ra khi bạn làm việc với các đối tượng thông qua kiểu cha (parent type):
<?php
class Animal {
public function speak() {
return "Some sound";
}
}
class Dog extends Animal {
public function speak() {
return "Woof!";
}
}
class Cat extends Animal {
public function speak() {
return "Meow!";
}
}
function makeAnimalSpeak(Animal $animal) {
return $animal->speak();
}
echo makeAnimalSpeak(new Dog()) . "\n";
echo makeAnimalSpeak(new Cat());
Đầu ra:
Woof!
Meow!Hàm makeAnimalSpeak() nhận bất kỳ đối tượng Animal nào. Hàm không biết và cũng không quan tâm nó nhận đối tượng Dog hay Cat. PHP tự động gọi phương thức đã ghi đè phù hợp dựa trên kiểu thực tế của đối tượng trong lúc chạy.
Đây là tính đa hình trong thực tế.
Cách tiếp cận này giúp bạn viết code linh hoạt, hoạt động với một nhóm đối tượng có liên quan mà không cần biết kiểu cụ thể của chúng. Sau này, bạn có thể thêm các lớp động vật mới, và hàm sẽ tự động hoạt động với chúng.
Điểm chính: Ghi đè phương thức (method overriding) cho phép thực hiện tính đa hình (polymorphism), nhờ đó các lớp khác nhau có thể phản hồi khác nhau với cùng một lời gọi phương thức, tùy theo kiểu thực tế của đối tượng tại thời điểm chạy.
Thử thách
DễHãy xây dựng một hệ thống nhạc cụ để minh họa tính đa hình thông qua việc ghi đè phương thức. Bạn sẽ tạo một lớp cơ sở Instrument và hai lớp con, mỗi lớp tạo ra âm thanh riêng, sau đó dùng một hàm để chơi bất kỳ nhạc cụ nào theo cách đa hình.
Bạn sẽ sắp xếp code trong bốn tệp:
Instrument.php: Tạo một lớpInstrumentcó thuộc tính$namevới phạm vi bảo vệ, được thiết lập thông qua hàm khởi tạo. Thêm phương thứcplay()trả về"[name] makes a sound". Đây là hành vi cơ sở mà các lớp con sẽ ghi đè.Guitar.php: Tạo lớpGuitarkế thừaInstrument. Bao gồm tệp lớp cha. Hàm khởi tạo nhận tên và truyền tên đó cho hàm khởi tạo của lớp cha. Ghi đè phương thứcplay()để trả về"[name] strums a chord".Drum.php: Tạo lớpDrumkế thừaInstrument. Bao gồm tệp lớp cha. Hàm khởi tạo nhận tên và truyền tên đó cho hàm khởi tạo của lớp cha. Ghi đè phương thứcplay()để trả về"[name] beats a rhythm".main.php: Bao gồm cả hai tệp Guitar và Drum. Tạo một hàm có tênperformWithnhận một tham số kiểuInstrument(có khai báo kiểu) và trả về kết quả gọiplay()trên đối tượng đó. Hàm này minh họa tính đa hình. Hàm hoạt động với mọi loại nhạc cụ nhờ khai báo kiểu lớp cha.
Bạn sẽ nhận hai đầu vào: tên đàn guitar và tên trống. Tạo một Guitar và một Drum với những tên này. Truyền từng đối tượng vào hàm performWith() rồi in ra kết quả: đàn guitar trước, sau đó đến trống, mỗi kết quả trên một dòng riêng.
Hãy chú ý cách performWith() chấp nhận mọi Instrument, nhưng PHP tự động gọi phương thức play() đã ghi đè phù hợp dựa trên kiểu đối tượng thực tế khi chạy. Đó chính là tính đa hình đang hoạt động!
Tự làm thử
<?php
// Nạp các tệp nhạc cụ
require_once 'Guitar.php';
require_once 'Drum.php';
// Đọc đầu vào
$guitarName = trim(fgets(STDIN));
$drumName = trim(fgets(STDIN));
// TODO: Tạo một hàm (function) tên là performWith với các yêu cầu sau:
// - Nhận một tham số (parameter) kiểu Instrument (dùng khai báo kiểu: Instrument $instrument)
// - Trả về kết quả khi gọi play() trên nhạc cụ
// TODO: Tạo một Guitar với $guitarName và một Drum với $drumName
// TODO: Truyền từng đối tượng vào performWith() rồi in kết quả ra (guitar trước, drum sau)
?>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