Tính bao gói (Encapsulation) là một trong 4 tính chất của lập trình hướng đối tượng. Nó là cơ chế cho phép ẩn những thông tin không liên quan và hiển thị những thông tin có liên quan.
Trong Java để đảm bảo được tính bao gói, ngta dùng access modifier private cho các thuộc tính. Các method thao tác với các thuộc tính ấy người ta dùng getter và setter để lấy ra thuộc tính và đặt lại giá trị cho nó. Các method này thường được sử dụng access modifer public. Ví dụ:
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Qua đây chúng ta có thể tạo ra một lớp chỉ ghi, chỉ có setter hoặc chỉ đọc, chỉ có getter.
Vậy làm thế nào để đảm bảo bao đóng với các trường dữ liệu là tham chiếu. Ví dụ ta có lớp StudentManager như sau:
public class StudentManager {
private List<Student> studentList;
public List<Student> getStudentList() {
return studentList;
}
public void setStudentList(List<Student> studentList) {
this.studentList = studentList;
}
}
Phương thức getStudent trả về cho chương trình studentList của StudentManager, vì đây là một biến tham chiếu nên trong ví dụ sau tất cả các thao tác trên biến students1 sẽ thay đổi các giá trị trên thuộc tính students của đối tượng manager. Điều này sẽ không đảm bảo được tính bao gói.
StudentManager manager = new StudentManager();
List<Student> students = new ArrayList<>();
students.add(new Student("Nam"));
students.add(new Student("Minh"));
manager.setStudentList(students);
List<Student> students1 = manager.getStudentList();
students1.add(new Student("Hoang"));
System.out.println(manager.getStudentList().size());
Giá trị được in ra sẽ là 3, có nghĩa là chương trình có thể dùng biến students1 để thay đổi thuộc tính của biến manager.
Vì vậy với các thuộc tính dạng tham chiếu, phương thức getter của nó phải làm 3 bước như sau để đảm bảo dữ liệu trả về đúng là giá trị hiện tại, tuy nhiên không trả về tham chiếu của nó:
Bước 1: tạo ra 1 biến tham chiếu mới
Bước 2: clone toàn bộ dữ liệu của tham chiếu cũ sang biến mới
Bước 3: trả về biến tham chiếu mới
Ta sẽ sửa lại StudentManager như sau:
public class StudentManager {
private List<Student> studentList;
public List<Student> getStudentList() {
//tạo ra 1 biến tham chiếu mới students
List<Student> students = new ArrayList<>();
//clone dữ liệu của studentList sang cho biến students
for (int i = 0; i < this.studentList.size(); i++) {
students.add(this.studentList.get(i));
}
//trả về biến tham chiếu mới
return students;
// return studentList;
}
public void setStudentList(List<Student> studentList) {
this.studentList = studentList;
}
}
Sau khi sửa lại phương thức getStudentList thì chương trình trên sẽ trả về 2. Và chúng ta đã đảm bảo được tính bao gói của thuộc tính tham chiếu. Oh yea.

Leave a Reply