Kế thừa là một trong những nguyên tắc cơ bản của phương pháp lập trình hướng đối tượng. Kế thừa là một cách tiếp cận mô hình hóa phần mềm cho phép mở rộng khả năng của một lớp hiện có để xây dựng lớp mới thay vì phải xây dựng từ đầu.
PHP cung cấp tất cả các chức năng để thực hiện kế thừa trong mô hình đối tượng của nó. Việc tích hợp kế thừa trong phát triển phần mềm PHP mang lại kết quả là tái sử dụng mã, loại bỏ sự trùng lặp mã không cần thiết và tổ chức logic.
Hãy tưởng tượng rằng bạn cần thiết kế một lớp mới mà hầu hết các chức năng đã được định nghĩa tốt trong một lớp hiện có. Kế thừa cho phép bạn mở rộng lớp hiện có, thêm hoặc xóa các tính năng của nó và phát triển một lớp mới. Trên thực tế, PHP có từ khóa "extends" để thiết lập mối quan hệ kế thừa giữa các lớp hiện có và lớp mới.
class newclass extends oldclass { ... ... }
Kế thừa xuất hiện khi một lớp mới (từ giờ sẽ được gọi là lớp kế thừa, lớp con, lớp con, v.v.) có mối quan hệ "LÀ MỘT" với một lớp hiện có (sẽ được gọi là lớp cơ sở, lớp siêu, lớp cha, v.v.).
Trong PHP, khi một lớp mới được định nghĩa bằng cách mở rộng một lớp khác, lớp con sẽ kế thừa các phương thức, thuộc tính và hằng số công khai và bảo vệ từ lớp cha. Bạn có thể tự do ghi đè chức năng của một phương thức đã kế thừa, nếu không nó sẽ giữ nguyên chức năng như đã được định nghĩa trong lớp cha.
Hãy xem xét ví dụ sau −
<?php class myclass { public function hello() { echo "Hello from the parent class" . PHP_EOL; } public function thanks() { echo "Thank you from parent class" . PHP_EOL; } } class newclass extends myclass { public function thanks() { echo "Thank you from the child class" . PHP_EOL; } } # object of parent class $obj1 = new myclass; $obj1->hello(); $obj1->thanks(); # object of child class $obj2 = new newclass; $obj2->hello(); $obj2->thanks(); ?>
Nó sẽ tạo ra output −
Hello from the parent class Thank you from parent class Hello from the parent class Thank you from the child class
Như đã đề cập trước đó, lớp con kế thừa các thành viên công khai và bảo vệ (thuộc tính và phương thức) của lớp cha. Lớp con có thể giới thiệu thêm các thuộc tính hoặc phương thức.
Trong ví dụ dưới đây, chúng ta sử dụng Book class làm lớp cha. Ở đây, chúng ta tạo ra một ebook class mở rộng từ lớp Book. Lớp mới có một thuộc tính bổ sung – format (chỉ định định dạng tệp của ebook – EPUB, PDF, MOBI, v.v.). Lớp ebook định nghĩa hai phương thức mới để khởi tạo và xuất dữ liệu ebook – getebook() và dispebook() tương ứng.
Mã hoàn chỉnh của ví dụ về kế thừa được trình bày dưới đây −
<?php class Book { /* Member variables */ protected int $price; protected string $title; public function getbook(string $param1, int $param2) { $this->title = $param1; $this->price = $param2; } public function dispbook() { echo "Title: $this->title Price: $this->price \n"; } } class ebook extends Book { private string $format; public function getebook(string $param1, int $param2, string $param3) { $this->title = $param1; $this->price = $param2; $this->format = $param3; } public function dispebook() { echo "Title: $this->title Price: $this->price\n"; echo "Format: $this->format \n"; } } $eb = new ebook; $eb->getebook("PHP Fundamentals", 450, "EPUB"); $eb->dispebook(); ?>
Trình duyệt output được hiển thị như dưới đây −
Title: PHP Fundamentals Price: 450 Format: EPUB
Nếu bạn nhìn kỹ vào hàm getebook(), hai câu lệnh gán đầu tiên thực chất là hàm getbook() mà lớp ebook đã kế thừa. Do đó, chúng ta có thể gọi nó bằng từ khóa parent và toán tử giải quyết phạm vi.
Thay đổi mã của hàm getebook() với đoạn mã sau -
public function getebook(string $param1, int $param2, string $param3) { parent::getbook($param1, $param2); $this->format = $param3; }
Tương tự, câu lệnh echo đầu tiên trong hàm dispebook() được thay thế bằng một lời gọi đến hàm dispbook() trong lớp cha.
public function dispebook() { parent::dispbook(); echo "Format: $this->format<br/>"; }
Constructor trong lớp cha được kế thừa bởi lớp con, nhưng nó không thể được gọi trực tiếp trong lớp con nếu lớp con định nghĩa một constructor.
Để chạy một constructor của lớp cha, cần phải gọi parent::__construct() trong constructor của lớp con.
Hãy xem xét ví dụ sau −
<?php class myclass{ public function __construct(){ echo "This is parent constructor". PHP_EOL; } } class newclass extends myclass { public function __construct(){ parent::__construct(); echo "This is child class destructor" . PHP_EOL; } } $obj = new newclass(); ?>
Nó sẽ tạo ra output −
This is parent constructor This is child class destructor
Tuy nhiên, nếu lớp con không có hàm khởi tạo, thì nó có thể được kế thừa từ lớp cha giống như một phương thức lớp bình thường (nếu nó không được khai báo là private).
Hãy xem xét ví dụ sau −
<?php class myclass{ public function __construct(){ echo "This is parent constructor". PHP_EOL; } } class newclass extends myclass{ } $obj = new newclass(); ?>
Nó sẽ tạo ra output −
This is parent constructor
PHP không cho phép phát triển một lớp bằng cách mở rộng từ nhiều lớp cha. Bạn có thể có hierarchical inheritance , trong đó lớp B mở rộng lớp A, lớp C mở rộng lớp B, và cứ như vậy. Nhưng PHP không hỗ trợ multiple inheritance nơi lớp C cố gắng mở rộng cả lớp A và lớp B. Tuy nhiên, chúng ta có thể mở rộng một lớp và triển khai một hoặc nhiều interfaces . Chúng ta sẽ tìm hiểu về giao diện trong một trong những chương sau.