Bài 2: Encapsulation (Đóng gói) trong Java
I. Định nghĩa và lợi ích của Encapsulation
Định nghĩa Encapsulation:
Encapsulation (Đóng gói) là quá trình gói gọn dữ liệu (các biến) và các phương thức thao tác trên dữ liệu đó trong một đơn vị duy nhất, thường là một lớp (class). Dữ liệu của đối tượng được bảo vệ khỏi sự truy cập không hợp lệ từ bên ngoài bằng cách sử dụng các access modifier như private, protected, và public.
Lợi ích của Encapsulation:
Bảo vệ dữ liệu: Ngăn chặn sự truy cập và thay đổi dữ liệu trực tiếp từ bên ngoài. Dữ liệu chỉ có thể được truy cập và thay đổi thông qua các phương thức được chỉ định (getter và setter).
Kiểm soát truy cập: Chỉ cho phép các thành phần của đối tượng hoặc lớp khác truy cập dữ liệu một cách kiểm soát thông qua các phương thức getter và setter.
Tăng tính bảo trì: Khi cần thay đổi cấu trúc dữ liệu nội bộ, bạn chỉ cần thay đổi trong lớp, không ảnh hưởng đến mã nguồn bên ngoài.
Ẩn chi tiết triển khai: Chỉ tiết lộ các chi tiết cần thiết cho người dùng và ẩn các chi tiết cài đặt không cần thiết.
II. Cách thực hiện Encapsulation trong Java
Sử dụng private access modifier:
Biến instance (thuộc tính) của lớp được khai báo là private để ngăn chặn sự truy cập trực tiếp từ bên ngoài lớp.
Sử dụng getter và setter:
Cung cấp các phương thức getter để lấy giá trị của biến và setter để thay đổi giá trị của biến. Các phương thức này thường được khai báo là public để có thể truy cập từ bên ngoài.
Ví dụ cụ thể:
public class Person {
private String name;
private int age;
// Constructor
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Getter for name
public String getName() {
return name;
}
// Setter for name
public void setName(String name) {
this.name = name;
}
// Getter for age
public int getAge() {
return age;
}
// Setter for age
public void setAge(int age) {
if (age > 0) {
this.age = age;
} else {
System.out.println("Age must be positive");
}
}
}
Trong ví dụ trên, các biến name và age được khai báo là private, do đó chỉ có thể truy cập thông qua các phương thức getName, setName, getAge, và setAge.
III. Ví dụ minh họa
Tạo lớp với các thuộc tính private:
public class BankAccount {
private String accountNumber;
private double balance;
// Constructor
public BankAccount(String accountNumber, double balance) {
this.accountNumber = accountNumber;
this.balance = balance;
}
// Getter for accountNumber
public String getAccountNumber() {
return accountNumber;
}
// Setter for accountNumber
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
// Getter for balance
public double getBalance() {
return balance;
}
// Setter for balance
public void setBalance(double balance) {
if (balance >= 0) {
this.balance = balance;
} else {
System.out.println("Balance cannot be negative");
}
}
// Method to deposit money
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: " + amount);
} else {
System.out.println("Deposit amount must be positive");
}
}
// Method to withdraw money
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrew: " + amount);
} else {
System.out.println("Invalid withdrawal amount");
}
}
}
Sử dụng các phương thức getter và setter:
public class Main {
public static void main(String[] args) {
BankAccount account = new BankAccount("123456789", 1000.0);
// Sử dụng getter để lấy thông tin
System.out.println("Account Number: " + account.getAccountNumber());
System.out.println("Balance: " + account.getBalance());
// Sử dụng setter để thay đổi thông tin
account.setAccountNumber("987654321");
account.setBalance(1500.0);
System.out.println("Updated Account Number: " + account.getAccountNumber());
System.out.println("Updated Balance: " + account.getBalance());
// Gửi tiền vào tài khoản
account.deposit(500.0);
System.out.println("Balance after deposit: " + account.getBalance());
// Rút tiền khỏi tài khoản
account.withdraw(300.0);
System.out.println("Balance after withdrawal: " + account.getBalance());
}
}
IV. Bài tập thực hành
Bài tập: Tạo một lớp Person với các thuộc tính được đóng gói và các phương thức getter và setter.
Yêu cầu:
Tạo lớp
Personvới các thuộc tínhname,age, vàaddress.Đóng gói các thuộc tính bằng cách sử dụng access modifier
private.Cung cấp các phương thức getter và setter cho các thuộc tính này.
Viết một chương trình chính để tạo đối tượng
Person, thay đổi và truy xuất thông tin thông qua các phương thức getter và setter.
Mã nguồn mẫu:
public class Person {
private String name;
private int age;
private String address;
// Constructor
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
// Getter for name
public String getName() {
return name;
}
// Setter for name
public void setName(String name) {
this.name = name;
}
// Getter for age
public int getAge() {
return age;
}
// Setter for age
public void setAge(int age) {
if (age > 0) {
this.age = age;
} else {
System.out.println("Age must be positive");
}
}
// Getter for address
public String getAddress() {
return address;
}
// Setter for address
public void setAddress(String address) {
this.address = address;
}
public static void main(String[] args) {
Person person = new Person("Alice", 30, "123 Main St");
// Sử dụng getter để lấy thông tin
System.out.println("Name: " + person.getName());
System.out.println("Age: " + person.getAge());
System.out.println("Address: " + person.getAddress());
// Sử dụng setter để thay đổi thông tin
person.setName("Bob");
person.setAge(25);
person.setAddress("456 Oak St");
System.out.println("Updated Name: " + person.getName());
System.out.println("Updated Age: " + person.getAge());
System.out.println("Updated Address: " + person.getAddress());
}
}
Tổng kết
Bài học này cung cấp một cái nhìn chi tiết về Encapsulation (Đóng gói) trong Java, bao gồm định nghĩa, lợi ích, cách thực hiện, và các ví dụ minh họa. Việc nắm vững khái niệm này sẽ giúp bạn bảo vệ dữ liệu và tăng cường tính bảo trì của mã nguồn trong các dự án phần mềm.