Tin Tức

Tổng hợp các bài viết, kinh nghiệm, chia sẻ kiến thức hữu ích về việc làm onsite, nhân sự onsite.

OOP In Real Life!!

folder Kiến thức công nghệ
today 24/07/2024 10:15
Lập trình hướng đối tượng (OOP) là một mô hình lập trình máy tính tổ chức thiết kế phần mềm xoay quanh dữ liệu hoặc đối tượng, thay vì các hàm và logic. Một đối tượng có thể được định nghĩa là một trường dữ liệu có các thuộc tính và hành vi riêng biệt.

OOP tập trung vào các đối tượng mà nhà phát triển muốn thao tác thay vì logic cần thiết để thao tác chúng. Phương pháp lập trình này rất phù hợp cho các chương trình lớn, phức tạp và được cập nhật hoặc bảo trì thường xuyên. Bốn trụ cột của Lập trình Hướng đối tượng sẽ được liệt kê dưới đây theo từng ví dụ thực tế và code minh họa của nó bằng Java: 

1. Kế thừa:

Ví dụ thực tế về kế thừa là con cái và cha mẹ, tất cả các thuộc tính của cha mẹ được truyền lại cho người con. Họ có các đặc điểm giống nhau nhưng không hoàn toàn giống nhau.

father and son

Code minh họa:

// Lớp cha (Parent class)
class Parent {
    // Thuộc tính của cha
    String familyName = "Nguyen";
    
    // Phương thức của cha
    void showFamilyName() {
        System.out.println("Family Name: " + familyName);
    }
}

// Lớp con (Child class) kế thừa từ lớp cha
class Child extends Parent {
    // Thuộc tính của con
    String givenName;
    
    // Constructor để khởi tạo tên của con
    Child(String givenName) {
        this.givenName = givenName;
    }
    
    // Phương thức của con
    void showFullName() {
        System.out.println("Full Name: " + givenName + " " + familyName);
    }
}

public class Main {
    public static void main(String[] args) {
        // Tạo đối tượng con
        Child child = new Child("An");
        
        // Gọi phương thức của cha (kế thừa)
        child.showFamilyName();
        
        // Gọi phương thức của con
        child.showFullName();
    }
}

Giải thích:

  • Lớp Parent đại diện cho cha, có thuộc tính familyName và phương thức showFamilyName().
  • Lớp Child kế thừa từ lớp Parent, thêm thuộc tính givenName và phương thức showFullName().
  • Trong phương thức main(), chúng ta tạo một đối tượng Child và gọi các phương thức để hiển thị tên họ và tên đầy đủ.

Kết quả:

Family Name: Nguyen
Full Name: An Nguyen

2. Đa hình:

Một ví dụ về Đa hình có thể được hình dung qua các vai trò của một người đàn ông. Người đàn ông chỉ có một, nhưng anh ta đảm nhận nhiều vai trò khác nhau: anh ta là một người cha đối với con mình, anh ta là một nhân viên, một người anh em và còn nhiều hơn nữa. Đây được gọi là Đa hình.

Man

Code minh họa:

// Lớp cơ sở (Base class)
class Man {
    // Phương thức cơ sở
    void performRole() {
        System.out.println("The man performs a role.");
    }
}

// Lớp con (Child class) đại diện cho vai trò là cha
class Father extends Man {
    @Override
    void performRole() {
        System.out.println("The man is a father.");
    }
}

// Lớp con khác đại diện cho vai trò là nhân viên
class Employee extends Man {
    @Override
    void performRole() {
        System.out.println("The man is an employee.");
    }
}

// Lớp con khác đại diện cho vai trò là anh em
class Brother extends Man {
    @Override
    void performRole() {
        System.out.println("The man is a brother.");
    }
}

public class Main {
    public static void main(String[] args) {
        // Tạo các đối tượng của các lớp con
        Man father = new Father();
        Man employee = new Employee();
        Man brother = new Brother();
        
        // Gọi phương thức performRole() với tính đa hình
        father.performRole();  // Outputs: The man is a father.
        employee.performRole(); // Outputs: The man is an employee.
        brother.performRole();  // Outputs: The man is a brother.
    }
}

Giải thích:

  • Lớp Man là lớp cơ sở với phương thức performRole().
  • Các lớp Father, Employee, và Brother kế thừa từ lớp Man và ghi đè phương thức performRole() để thể hiện các vai trò khác nhau.
  • Trong phương thức main(), chúng ta tạo các đối tượng của các lớp con và gọi phương thức performRole() để thấy sự khác biệt trong hành vi của mỗi lớp.

Kết quả:

The man is a father.
The man is an employee.
The man is a brother.

3. Đóng gói:

Một trong những ví dụ thực tế về đóng gói là viên thuốc, vì viên thuốc bao bọc, bảo vệ tất cả các thành phần thuốc bên trong nó, tương tự như trong Java, các đơn vị đóng gói (lớp, giao diện, enum, v.v.) bao gồm tất cả dữ liệu và hành vi bên trong nó.

Code minh họa:

// Lớp Capsule đại diện cho viên thuốc
class Capsule {
    // Các thuộc tính được đóng gói (private)
    private String medicineName;
    private double dosage;
    
    // Constructor để khởi tạo đối tượng Capsule
    Capsule(String medicineName, double dosage) {
        this.medicineName = medicineName;
        this.dosage = dosage;
    }
    
    // Phương thức truy cập công khai (getter) cho thuộc tính medicineName
    public String getMedicineName() {
        return medicineName;
    }
    
    // Phương thức thiết lập công khai (setter) cho thuộc tính medicineName
    public void setMedicineName(String medicineName) {
        this.medicineName = medicineName;
    }
    
    // Phương thức truy cập công khai (getter) cho thuộc tính dosage
    public double getDosage() {
        return dosage;
    }
    
    // Phương thức thiết lập công khai (setter) cho thuộc tính dosage
    public void setDosage(double dosage) {
        if (dosage > 0) { // Kiểm tra tính hợp lệ của dữ liệu
            this.dosage = dosage;
        }
    }
    
    // Phương thức hiển thị thông tin viên thuốc
    public void displayInfo() {
        System.out.println("Medicine Name: " + medicineName);
        System.out.println("Dosage: " + dosage + " mg");
    }
}

public class Main {
    public static void main(String[] args) {
        // Tạo đối tượng Capsule
        Capsule capsule = new Capsule("Aspirin", 500);
        
        // Hiển thị thông tin sử dụng phương thức public
        capsule.displayInfo();
        
        // Thay đổi thuộc tính sử dụng setter
        capsule.setMedicineName("Paracetamol");
        capsule.setDosage(650);
        
        // Hiển thị thông tin sau khi thay đổi
        capsule.displayInfo();
    }
}

Giải thích:

  • Lớp Capsule đại diện cho viên thuốc, với các thuộc tính medicineNamedosage được đóng gói bằng cách khai báo chúng là private. Điều này bảo vệ dữ liệu không bị truy cập trực tiếp từ bên ngoài lớp.
  • Các phương thức getMedicineName(), setMedicineName(), getDosage(), và setDosage() được cung cấp để truy cập và thay đổi giá trị của các thuộc tính này. Phương thức setDosage() cũng kiểm tra tính hợp lệ của dữ liệu trước khi thay đổi.
  • Phương thức displayInfo() được sử dụng để hiển thị thông tin của viên thuốc.

Kết quả:

Medicine Name: Aspirin
Dosage: 500.0 mg
Medicine Name: Paracetamol
Dosage: 650.0 mg

4. Trừu tượng

Giấu đi các chi tiết phức tạp và chỉ hiển thị những gì cần thiết. Ví dụ: chúng ta đều sử dụng ATM để rút tiền, chuyển tiền, lấy bản sao kê ngắn, v.v. trong cuộc sống hàng ngày. Nhưng chúng ta không biết bên trong ATM đang diễn ra những gì khi bạn đưa thẻ ATM vào để thực hiện các loại giao dịch.

ATM

Code minh họa:

// Lớp trừu tượng ATM
abstract class ATM {
    // Phương thức trừu tượng (Abstract method) mà các lớp con phải thực hiện
    abstract void performTransaction();
    
    // Phương thức cụ thể có sẵn trong lớp trừu tượng
    void displayMessage(String message) {
        System.out.println(message);
    }
}

// Lớp con thực hiện phương thức trừu tượng cho giao dịch rút tiền
class WithdrawalATM extends ATM {
    @Override
    void performTransaction() {
        displayMessage("Performing cash withdrawal...");
        // Thực hiện các bước rút tiền ở đây
    }
}

// Lớp con thực hiện phương thức trừu tượng cho giao dịch chuyển tiền
class TransferATM extends ATM {
    @Override
    void performTransaction() {
        displayMessage("Performing money transfer...");
        // Thực hiện các bước chuyển tiền ở đây
    }
}

// Lớp con thực hiện phương thức trừu tượng cho việc kiểm tra số dư
class BalanceCheckATM extends ATM {
    @Override
    void performTransaction() {
        displayMessage("Checking account balance...");
        // Thực hiện các bước kiểm tra số dư ở đây
    }
}

public class Main {
    public static void main(String[] args) {
        // Tạo các đối tượng của các lớp con
        ATM withdrawal = new WithdrawalATM();
        ATM transfer = new TransferATM();
        ATM balanceCheck = new BalanceCheckATM();
        
        // Thực hiện các giao dịch với tính trừu tượng
        withdrawal.performTransaction(); // Outputs: Performing cash withdrawal...
        transfer.performTransaction(); // Outputs: Performing money transfer...
        balanceCheck.performTransaction(); // Outputs: Checking account balance...
    }
}

Giải thích:

  • Lớp ATM là lớp trừu tượng với phương thức trừu tượng performTransaction(), yêu cầu các lớp con phải thực hiện phương thức này. Lớp ATM cũng cung cấp phương thức cụ thể displayMessage() để hiển thị thông điệp.
  • Các lớp con WithdrawalATM, TransferATM, và BalanceCheckATM kế thừa từ lớp ATM và thực hiện phương thức trừu tượng performTransaction() theo cách riêng của chúng để xử lý các giao dịch rút tiền, chuyển tiền, và kiểm tra số dư.
  • Trong phương thức main(), các đối tượng của các lớp con được tạo ra và phương thức performTransaction() được gọi để thực hiện các giao dịch cụ thể.

Kết quả:

Performing cash withdrawal...
Performing money transfer...
Checking account balance...

Như vậy:

Lập trình hướng đối tượng (OOP) với bốn trụ cột chính đã được nêu trên cung cấp một cách tiếp cận hiệu quả cho việc thiết kế và phát triển phần mềm. Bằng cách tập trung vào các đối tượng và mối quan hệ giữa chúng, OOP giúp giảm độ phức tạp của mã nguồn, tăng tính linh hoạt, và cải thiện khả năng bảo trì của các chương trình phần mềm. Hiểu rõ và áp dụng các nguyên tắc OOP không chỉ giúp các nhà phát triển tạo ra các ứng dụng mạnh mẽ và đáng tin cậy mà còn giúp họ thích ứng nhanh chóng với các yêu cầu và thay đổi trong quá trình phát triển phần mềm.