Menu
CoddyTech

Tìm hiểu sâu về bộ điều chỉnh quyền truy cập

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

Bây giờ bạn đã hiểu ba phạm vi truy cập, hãy cùng tìm hiểu cách chúng hoạt động trong các tình huống kế thừa. Điều quan trọng cần nhớ là các thành viên protected có thể được truy cập từ các lớp con, còn các thành viên private vẫn bị ẩn ngay cả với lớp con.

<?php
class Vehicle {
    public $brand;
    protected $engineType;
    private $serialNumber;
    
    public function __construct($brand, $engine, $serial) {
        $this->brand = $brand;
        $this->engineType = $engine;
        $this->serialNumber = $serial;
    }
    
    private function getSerial() {
        return $this->serialNumber;
    }
    
    protected function getEngineInfo() {
        return $this->engineType;
    }
}

class Car extends Vehicle {
    public function getDetails() {
        return $this->brand . " - " . $this->getEngineInfo();
        // $this->serialNumber sẽ gây lỗi vì là thuộc tính private!
        // $this->getSerial() cũng sẽ gây lỗi vì là phương thức (method) private!
    }
}

$car = new Car("Toyota", "V6", "ABC123");
echo $car->getDetails();

Đầu ra:

Toyota - V6

Lớp Car có thể truy cập $brand (công khai) và gọi getEngineInfo() (được bảo vệ), nhưng không thể truy cập $serialNumber hoặc getSerial() vì chúng là riêng tư đối với Vehicle. Sự phân biệt này cho phép bạn chia sẻ một số chi tiết nội bộ với các lớp con, đồng thời giữ những chi tiết khác hoàn toàn ẩn.

Điểm chính: Dùng protected khi các lớp con cần truy cập dữ liệu hoặc phương thức nội bộ, và dùng private khi bạn không muốn ngay cả các lớp con truy cập vào một số chi tiết triển khai.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống quản lý thiết bị để tìm hiểu cách các phạm vi truy cập hoạt động trong kế thừa. Bạn sẽ tạo lớp cơ sở Device với các thuộc tính có mức độ hiển thị khác nhau, sau đó mở rộng lớp này bằng lớp Smartphone để minh họa những thành viên nào mà lớp con có thể và không thể truy cập.

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

  • Device.php: Tạo lớp Device đại diện cho các thiết bị điện tử có mức độ nhạy cảm dữ liệu khác nhau. Bao gồm:
    • Thuộc tính public $brand dùng để lưu tên nhà sản xuất
    • Thuộc tính protected $modelNumber dùng để nhận dạng nội bộ
    • Thuộc tính private $manufacturingCode dùng để lưu dữ liệu chỉ dành cho nhà máy
    Hàm khởi tạo cần nhận cả ba giá trị. Thêm phương thức private getManufacturingCode() để trả về mã sản xuất. Thêm phương thức public getModelInfo() để trả về "Model: [modelNumber]". Cuối cùng, thêm phương thức public getFullCode() để trả về "[brand]-[manufacturingCode]". Điều này cho thấy bản thân lớp có thể truy cập các thành viên private của nó.
  • Smartphone.php: Tạo lớp Smartphone kế thừa Device. Thêm tệp Device. Hàm khởi tạo cần nhận brand, modelNumber, manufacturingCode và tên hệ điều hành. Gọi hàm khởi tạo của lớp cha với ba giá trị đầu tiên, sau đó lưu hệ điều hành vào một thuộc tính private. Thêm phương thức public getDeviceDetails() để trả về "[brand] [modelNumber] running [os]". Lưu ý rằng bạn có thể truy cập trực tiếp thuộc tính public $brand và thuộc tính protected $modelNumber, nhưng không thể truy cập trực tiếp thuộc tính private $manufacturingCode: thay vào đó, bạn cần dùng phương thức public được kế thừa getFullCode().
  • main.php: Thêm tệp Smartphone. Bạn sẽ nhận bốn đầu vào: tên thương hiệu, số hiệu mẫu, mã sản xuất và hệ điều hành. Tạo một instance Smartphone với các giá trị này. In ra ba dòng:
    • Kết quả gọi getDeviceDetails()
    • Kết quả gọi phương thức getModelInfo() được kế thừa
    • Kết quả gọi phương thức getFullCode() được kế thừa

Thử thách này làm nổi bật điểm khác biệt chính: lớp Smartphone có thể tự do sử dụng thuộc tính protected $modelNumber được kế thừa từ Device, nhưng thuộc tính private $manufacturingCode và phương thức getManufacturingCode() vẫn hoàn toàn bị ẩn: chỉ có thể truy cập chúng thông qua giao diện public mà Device chọn để cung cấp.

Tự làm thử

<?php
require_once 'Smartphone.php';

// Đọc dữ liệu đầu vào
$brand = trim(fgets(STDIN));
$modelNumber = trim(fgets(STDIN));
$manufacturingCode = trim(fgets(STDIN));
$os = trim(fgets(STDIN));

// TODO: Tạo một instance của Smartphone bằng các giá trị đầu vào

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

// TODO: In ra kết quả của phương thức (method) getModelInfo() được kế thừa

// TODO: In ra kết quả của phương thức getFullCode() được kế thừa
?>
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