Bỏ qua để đến nội dung

Đóng gói (Encapsulation)

1. Vấn đề: field public không được bảo vệ

Phần tiêu đề “1. Vấn đề: field public không được bảo vệ”

Nếu thuộc tính là public, bất kỳ đoạn code nào cũng có thể gán giá trị bất hợp lệ trực tiếp, không qua kiểm tra:

public class Account {
public double balance; // public - AI CŨNG sửa được trực tiếp
}
Account acc = new Account();
acc.balance = -1000; // hợp lệ về mặt cú pháp, nhưng vô lý về nghiệp vụ! Không có gì ngăn cản

Đóng gói là nguyên tắc ẩn dữ liệu bên trong (khai báo private), chỉ cho phép truy cập/thay đổi thông qua các phương thức công khai (getter/setter) - nơi có thể kiểm tra tính hợp lệ:

public class Account {
private double balance; // private - CHỈ class Account tự truy cập trực tiếp được
public double getBalance() { // getter - đọc giá trị
return balance;
}
public void deposit(double amount) { // setter có kiểm tra - thay vì cho gán trực tiếp
if (amount > 0) {
balance += amount;
} else {
System.out.println("Số tiền nạp phải dương!");
}
}
}
Account acc = new Account();
acc.deposit(1000); // OK
acc.deposit(-500); // bị từ chối, in cảnh báo - balance không bị thay đổi sai
// acc.balance = -1000; // LỖI BIÊN DỊCH! balance là private, không truy cập trực tiếp được từ ngoài class
Modifier Cùng class Cùng package Lớp con khác package Nơi khác
private
(không ghi gì - package-private)
protected
public

Quy ước phổ biến: field khai báo private, phương thức cần dùng từ bên ngoài khai báo public.

public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("Tuổi không thể âm");
}
this.age = age;
}
}
  • Kiểm soát dữ liệu: đảm bảo dữ liệu luôn ở trạng thái hợp lệ thông qua setter có kiểm tra
  • Ẩn chi tiết cài đặt: có thể thay đổi cách lưu trữ dữ liệu bên trong mà không ảnh hưởng code bên ngoài (miễn là getter/setter giữ nguyên hành vi)
  • Chỉ công khai những gì cần thiết: giảm sự phụ thuộc không cần thiết giữa các phần code
  • Đóng gói: khai báo field private, truy cập qua getter/setter public có kiểm tra
  • private chỉ truy cập được trong cùng class; public truy cập được từ mọi nơi
  • Setter cho phép kiểm tra tính hợp lệ trước khi thay đổi trạng thái đối tượng - điều field public không làm được