Menu
CoddyTech

Công khai, được bảo vệ, riêng tư

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

Chào mừng bạn đến với chương về tính đóng gói! Tính đóng gói giúp kiểm soát quyền truy cập vào dữ liệu bên trong lớp của bạn. PHP cung cấp ba phạm vi truy cập để xác định nơi có thể truy cập thuộc tính và phương thức: public, protected và private.

Sau đây là cách hoạt động của từng từ sửa đổi:

<?php
class BankAccount {
    public $accountHolder;    // Có thể truy cập từ mọi nơi
    protected $accountNumber; // Có thể truy cập trong lớp này và các lớp con
    private $balance;         // Chỉ có thể truy cập trong lớp này
    
    public function __construct($holder, $number, $balance) {
        $this->accountHolder = $holder;
        $this->accountNumber = $number;
        $this->balance = $balance;
    }
    
    public function getBalance() {
        return $this->balance;
    }
}

$account = new BankAccount("John", "12345", 1000);

echo $account->accountHolder . "\n";  // Chạy được vì có quyền truy cập công khai
echo $account->getBalance();          // Chạy được vì đây là phương thức công khai

Đầu ra:

John
1000

Truy cập trực tiếp vào $account->balance sẽ gây ra lỗi vì thuộc tính này là riêng tư. Điều tương tự cũng áp dụng với $account->accountNumber khi truy cập từ bên ngoài hệ thống phân cấp lớp. Cơ chế bảo vệ này đảm bảo rằng chỉ có thể sửa đổi dữ liệu nhạy cảm thông qua các phương thức được kiểm soát.

Bộ điều chỉnhCùng lớpLớp conBên ngoài
publicCóCóCó
protectedCóCóKhông
privateCóKhôngKhông

Điểm chính: Dùng private cho dữ liệu nội bộ không nên được truy cập trực tiếp, protected cho dữ liệu mà các lớp con cần dùng và chỉ dùng public để cho phép truy cập từ bên ngoài một cách an toàn.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống quản lý nhân viên an toàn để minh họa cách các bộ sửa đổi quyền truy cập bảo vệ dữ liệu nhạy cảm. Bạn sẽ tạo một hệ thống phân cấp lớp, trong đó các cấp thông tin khác nhau có thể được truy cập tùy theo nơi code đang chạy: bên trong lớp, trong lớp con hoặc từ bên ngoài.

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

  • Employee.php: Tạo lớp Employee để quản lý dữ liệu nhân viên với các cấp độ hiển thị phù hợp. Lớp này cần có:
    • Thuộc tính public $name lưu tên nhân viên, mọi người đều có thể xem an toàn
    • Thuộc tính protected $employeeId lưu mã nhân viên nội bộ, cần thiết cho các lớp con
    • Thuộc tính private $salary lưu thông tin lương nhạy cảm, chỉ lớp này mới có thể truy cập trực tiếp
    Hàm khởi tạo cần nhận cả ba giá trị và gán chúng. Thêm phương thức công khai getSalary() để trả về mức lương riêng tư. Đây là cách có kiểm soát để truy cập dữ liệu được bảo vệ. Đồng thời, thêm phương thức công khai getPublicInfo() để trả về "[name] works here".
  • Manager.php: Tạo lớp Manager kế thừa Employee. Bao gồm tệp Employee. Hàm khởi tạo cần nhận tên, employeeId, salary và tên phòng ban. Gọi hàm khởi tạo của lớp cha với ba giá trị đầu tiên, sau đó lưu phòng ban vào một thuộc tính riêng tư. Thêm phương thức công khai getTeamInfo() để trả về "Manager [name] (ID: [employeeId]) leads [department]". Lưu ý rằng lớp con có thể truy cập $employeeId được bảo vệ, nhưng cần dùng getSalary() để truy cập mức lương riêng tư.
  • main.php: Bao gồm tệp Manager. Bạn sẽ nhận bốn đầu vào: tên, mã nhân viên, mức lương dưới dạng chuỗi để chuyển thành số nguyên và tên phòng ban. Tạo một đối tượng Manager bằng các giá trị này. In ra ba dòng:
    • Tên của người quản lý, được truy cập trực tiếp qua thuộc tính công khai
    • Kết quả gọi getTeamInfo()
    • Kết quả gọi getSalary()

Thử thách này minh họa cách đóng gói hoạt động: mọi người có thể tự do truy cập tên, mã nhân viên được chia sẻ với các lớp con thông qua khả năng hiển thị protected, còn mức lương vẫn được giữ kín trong lớp cha và chỉ có thể truy cập thông qua một phương thức công khai có kiểm soát.

Tự làm thử

<?php
require_once 'Manager.php';

// Đọc các giá trị đầu vào
$name = trim(fgets(STDIN));
$employeeId = trim(fgets(STDIN));
$salary = intval(trim(fgets(STDIN)));
$department = trim(fgets(STDIN));

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

// TODO: In ra tên của manager (truy cập trực tiếp qua thuộc tính public)

// TODO: In ra kết quả khi gọi getTeamInfo()

// TODO: In ra kết quả khi gọi getSalary()
?>
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