Menu
CoddyTech

Đặc tính và kế thừa

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 55 trên 91.

Giờ bạn đã hiểu trait hoạt động như thế nào, hãy cùng làm rõ khi nào nên dùng trait và khi nào nên dùng kế thừa. Cả hai đều cho phép tái sử dụng code, nhưng phục vụ những mục đích khác nhau và có các đặc điểm riêng.

Kế thừa thiết lập mối quan hệ “là một”. Lớp Dog kế thừa lớp Animal nghĩa là chó là một loài vật. Lớp con kế thừa danh tính của lớp cha và có thể được dùng ở bất cứ đâu cần kiểu của lớp cha.

Đặc tính cung cấp khả năng “có”. Khi một lớp sử dụng đặc tính Loggable, lớp đó có chức năng ghi nhật ký, nhưng không trở thành bộ ghi nhật ký. Đặc tính bổ sung hành vi mà không thay đổi bản chất của lớp.

<?php
// Kế thừa: Dog là một Animal
class Animal {
    public function breathe(): void {
        echo "Breathing";
    }
}

class Dog extends Animal {
    public function bark(): void {
        echo "Woof!";
    }
}

// Trait: Dog có khả năng ghi nhật ký
trait Loggable {
    public function log(string $msg): void {
        echo "Log: $msg";
    }
}

class Cat extends Animal {
    use Loggable;
}

Những điểm khác biệt chính cần ghi nhớ:

Khía cạnhKế thừaTraits
Mối quan hệlà mộtcó khả năng
Giới hạnChỉ có một lớp chaCó thể dùng nhiều trait
Kiểm tra kiểu dữ liệuHoạt động với instanceofKhông có định danh kiểu
Phù hợp nhất vớiCác mối quan hệ phân cấpCác hành vi dùng chung giữa những lớp không liên quan

Dùng kế thừa khi các lớp có chung một đặc điểm nhận dạng. Dùng trait khi các lớp không liên quan cần cùng một chức năng mà không thuộc cùng một hệ thống phân cấp.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống phương tiện để minh họa khi nào nên dùng kế thừa thay vì trait. Bạn sẽ tạo một hệ thống phân cấp các phương tiện có chung danh tính thông qua kế thừa, đồng thời bổ sung các khả năng dùng chung thông qua trait.

Bạn sẽ sắp xếp code trong bốn tệp:

  • Trackable.php: Tạo một trait tên là Trackable có khả năng theo dõi GPS. Trait này cần có:
    • Thuộc tính riêng tư $location (chuỗi)
    • Phương thức setLocation(string $location) lưu vị trí hiện tại
    • Phương thức getLocation() trả về "Location: [location]"
    Trait này thể hiện một khả năng theo quan hệ «có»: bất kỳ phương tiện nào cũng có thể có tính năng theo dõi, nhưng có tính năng theo dõi không biến một thứ thành phương tiện.
  • Vehicle.php: Tạo một lớp cơ sở Vehicle để thiết lập quan hệ «là». Thêm tệp trait vào. Dùng cú pháp khai báo thuộc tính trong hàm khởi tạo để định nghĩa thuộc tính $brand với phạm vi protected. Thêm phương thức describe() trả về "Vehicle: [brand]". Lớp này nên dùng trait Trackable vì mọi phương tiện trong đội xe của chúng ta đều có GPS.
  • Car.php: Tạo lớp Car kế thừa Vehicle. Thêm tệp Vehicle vào. Dùng cú pháp khai báo thuộc tính trong hàm khởi tạo để nhận thương hiệu và thuộc tính riêng tư $doors (số nguyên). Gọi hàm khởi tạo của lớp cha với thương hiệu. Ghi đè phương thức describe() để trả về "Car: [brand] with [doors] doors".
  • main.php: Thêm tệp Car vào. Bạn sẽ nhận ba đầu vào: tên thương hiệu, số cửa và một chuỗi chỉ vị trí. Tạo một đối tượng Car, đặt vị trí cho đối tượng đó, sau đó in ra hai dòng:
    • Kết quả gọi describe()
    • Kết quả gọi getLocation()

Hãy chú ý cách kế thừa và trait kết hợp với nhau ở đây: Car là một Vehicle (kế thừa xác lập danh tính), còn Vehicle có khả năng theo dõi (trait bổ sung hành vi). Bạn có thể dùng instanceof Vehicle để kiểm tra xem một thứ có phải là phương tiện hay không, nhưng không có kiểu «Trackable» để kiểm tra: đó là điểm khác biệt chính giữa hai cách tiếp cận này.

Tự làm thử

<?php
// Tệp chính: tạo và kiểm tra instance Car

// TODO: Nạp tệp Car.php

// Đọc dữ liệu đầu vào
$brand = trim(fgets(STDIN));
$doors = intval(trim(fgets(STDIN)));
$location = trim(fgets(STDIN));

// TODO: Tạo instance Car với brand và doors

// TODO: Đặt vị trí của xe

// TODO: In ra kết quả của describe()

// TODO: In ra kết quả của getLocation()
?>
quiz iconTự kiểm tra

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

Tự luyện tập: Trình biên dịch PHP online