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 - V6Lớ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.
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ớpDeviceđạ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$branddùng để lưu tên nhà sản xuất - Thuộc tính
protected$modelNumberdùng để nhận dạng nội bộ - Thuộc tính
private$manufacturingCodedùng để lưu dữ liệu chỉ dành cho nhà máy
privategetManufacturingCode()để trả về mã sản xuất. Thêm phương thứcpublicgetModelInfo()để trả về"Model: [modelNumber]". Cuối cùng, thêm phương thứcpublicgetFullCode()để 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ênprivatecủa nó.- Thuộc tính
Smartphone.php: Tạo lớpSmartphonekế thừaDevice. 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ínhprivate. Thêm phương thức publicgetDeviceDetails()để 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$brandvà 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ừagetFullCode().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 instanceSmartphonevớ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
- Kết quả gọi
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
?>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