Chuyển tới nội dung chính

Tính Đa Hình trong Java 🎨

🎯 Mục tiêu: Học cách sử dụng tính đa hình để tạo ra các đối tượng có thể có nhiều dạng khác nhau và thực hiện các hành vi khác nhau trong Java.

Giới thiệu 📝

Tính đa hình (Polymorphism) là một trong những tính năng cốt lõi của lập trình hướng đối tượng trong Java. Nó cho phép một đối tượng có thể có nhiều dạng khác nhau và thực hiện các hành vi khác nhau dựa trên ngữ cảnh.

💡 Fun Fact: Tính đa hình giúp chúng ta viết code linh hoạt hơn, dễ mở rộng hơn và có thể tái sử dụng code hiệu quả hơn.

1. Đa Hình Thời Gian Chạy (Runtime Polymorphism) ⚡

Ghi Đè Phương Thức (Method Overriding)

public class Animal {
public void makeSound() {
System.out.println("Tiếng kêu của động vật");
}
}

public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Gâu gâu!");
}
}

public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meo meo!");
}
}

// Sử dụng
Animal dog = new Dog();
Animal cat = new Cat();
dog.makeSound(); // In: "Gâu gâu!"
cat.makeSound(); // In: "Meo meo!"

Đa Hình với Constructor

public class Vehicle {
protected String brand;

public Vehicle(String brand) {
this.brand = brand;
}
}

public class Car extends Vehicle {
private int doors;

public Car(String brand, int doors) {
super(brand);
this.doors = doors;
}
}

2. Đa Hình Thời Gian Biên Dịch (Compile-time Polymorphism) 🔄

Nạp Chồng Phương Thức (Method Overloading)

public class Calculator {
public int add(int a, int b) {
return a + b;
}

public double add(double a, double b) {
return a + b;
}

public String add(String a, String b) {
return a + b;
}
}

// Sử dụng
Calculator calc = new Calculator();
int sum1 = calc.add(5, 3); // 8
double sum2 = calc.add(5.5, 3.2); // 8.7
String sum3 = calc.add("Hello", " World"); // "Hello World"

Nạp Chồng Constructor

public class Person {
private String name;
private int age;

public Person() {
this.name = "Unknown";
this.age = 0;
}

public Person(String name) {
this.name = name;
this.age = 0;
}

public Person(String name, int age) {
this.name = name;
this.age = age;
}
}

3. Đa Hình với Interface 🎯

Đa Hình qua Interface

public interface PaymentMethod {
void pay(double amount);
}

public class CreditCard implements PaymentMethod {
@Override
public void pay(double amount) {
System.out.println("Thanh toán " + amount + " bằng thẻ tín dụng");
}
}

public class PayPal implements PaymentMethod {
@Override
public void pay(double amount) {
System.out.println("Thanh toán " + amount + " bằng PayPal");
}
}

// Sử dụng
PaymentMethod payment = new CreditCard();
payment.pay(100.0); // Thanh toán bằng thẻ tín dụng
payment = new PayPal();
payment.pay(100.0); // Thanh toán bằng PayPal

Đa Hình với Abstract Class

public abstract class Shape {
protected String color;

public Shape(String color) {
this.color = color;
}

public abstract double getArea();
public abstract double getPerimeter();
}

public class Circle extends Shape {
private double radius;

public Circle(String color, double radius) {
super(color);
this.radius = radius;
}

@Override
public double getArea() {
return Math.PI * radius * radius;
}

@Override
public double getPerimeter() {
return 2 * Math.PI * radius;
}
}

public class Rectangle extends Shape {
private double width;
private double height;

public Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}

@Override
public double getArea() {
return width * height;
}

@Override
public double getPerimeter() {
return 2 * (width + height);
}
}

4. Ví Dụ Thực Tế 🚀

Quản Lý Nhân Viên

public abstract class Employee {
protected String name;
protected double salary;

public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}

public abstract double calculateBonus();
}

public class Manager extends Employee {
private double bonusRate;

public Manager(String name, double salary, double bonusRate) {
super(name, salary);
this.bonusRate = bonusRate;
}

@Override
public double calculateBonus() {
return salary * bonusRate;
}
}

public class Developer extends Employee {
private int projectsCompleted;

public Developer(String name, double salary, int projectsCompleted) {
super(name, salary);
this.projectsCompleted = projectsCompleted;
}

@Override
public double calculateBonus() {
return projectsCompleted * 1000;
}
}

Xử Lý Thanh Toán

public interface PaymentProcessor {
boolean processPayment(double amount);
void refund(double amount);
}

public class CreditCardProcessor implements PaymentProcessor {
@Override
public boolean processPayment(double amount) {
// Xử lý thanh toán bằng thẻ tín dụng
return true;
}

@Override
public void refund(double amount) {
// Xử lý hoàn tiền thẻ tín dụng
}
}

public class PayPalProcessor implements PaymentProcessor {
@Override
public boolean processPayment(double amount) {
// Xử lý thanh toán bằng PayPal
return true;
}

@Override
public void refund(double amount) {
// Xử lý hoàn tiền PayPal
}
}

Quản Lý Hệ Thống Báo Cáo

public abstract class Report {
protected String title;
protected String author;
protected Date date;

public Report(String title, String author) {
this.title = title;
this.author = author;
this.date = new Date();
}

public abstract void generate();
public abstract void format();
}

public class FinancialReport extends Report {
private double totalRevenue;
private double totalExpenses;

public FinancialReport(String title, String author) {
super(title, author);
this.totalRevenue = 0.0;
this.totalExpenses = 0.0;
}

@Override
public void generate() {
// Tạo báo cáo tài chính
System.out.println("Generating financial report...");
}

@Override
public void format() {
// Định dạng báo cáo tài chính
System.out.println("Formatting financial report...");
}
}

public class SalesReport extends Report {
private int totalSales;
private int totalCustomers;

public SalesReport(String title, String author) {
super(title, author);
this.totalSales = 0;
this.totalCustomers = 0;
}

@Override
public void generate() {
// Tạo báo cáo bán hàng
System.out.println("Generating sales report...");
}

@Override
public void format() {
// Định dạng báo cáo bán hàng
System.out.println("Formatting sales report...");
}
}

5. Best Practices ✅

  1. Sử Dụng Đa Hình Cho Các Hành Vi Chung

    // Không nên
    public class Dog {
    public void makeSound() {
    System.out.println("Gâu gâu!");
    }
    }

    public class Cat {
    public void makeSound() {
    System.out.println("Meo meo!");
    }
    }

    // Nên
    public abstract class Animal {
    public abstract void makeSound();
    }

    public class Dog extends Animal {
    @Override
    public void makeSound() {
    System.out.println("Gâu gâu!");
    }
    }

    public class Cat extends Animal {
    @Override
    public void makeSound() {
    System.out.println("Meo meo!");
    }
    }
  2. Sử Dụng Interface Cho Các Hành Vi Đa Dạng

    // Không nên
    public class PaymentProcessor {
    public void processCreditCard(double amount) { }
    public void processPayPal(double amount) { }
    }

    // Nên
    public interface PaymentMethod {
    void process(double amount);
    }

    public class CreditCard implements PaymentMethod {
    @Override
    public void process(double amount) { }
    }

    public class PayPal implements PaymentMethod {
    @Override
    public void process(double amount) { }
    }
  3. Sử Dụng Nạp Chồng Phương Thức Hợp Lý

    // Không nên
    public class Calculator {
    public int addInt(int a, int b) { }
    public double addDouble(double a, double b) { }
    }

    // Nên
    public class Calculator {
    public int add(int a, int b) { }
    public double add(double a, double b) { }
    }

6. Lỗi Thường Gặp ⚠️

  1. Quên Ghi Đè Phương Thức

    // Lỗi
    public abstract class Shape {
    public abstract double getArea();
    }

    public class Circle extends Shape {
    // Quên ghi đè getArea()
    }

    // Đúng
    public class Circle extends Shape {
    @Override
    public double getArea() {
    return Math.PI * radius * radius;
    }
    }
  2. Sai Kiểu Trả Về Khi Ghi Đè

    // Lỗi
    public class Parent {
    public Number getValue() {
    return 1;
    }
    }

    public class Child extends Parent {
    @Override
    public String getValue() { // Sai kiểu trả về
    return "1";
    }
    }

    // Đúng
    public class Child extends Parent {
    @Override
    public Number getValue() {
    return 1;
    }
    }
  3. Quên Gọi Super Trong Constructor

    // Lỗi
    public class Child extends Parent {
    public Child() {
    // Quên gọi super()
    }
    }

    // Đúng
    public class Child extends Parent {
    public Child() {
    super();
    }
    }

7. Ví Dụ Thực Tế Nâng Cao 🎯

Quản Lý Hệ Thống Đa Phương Tiện

public interface MediaPlayer {
void play();
void pause();
void stop();
}

public interface MediaRecorder {
void record();
void pauseRecording();
void stopRecording();
}

public class AudioPlayer implements MediaPlayer {
private String currentTrack;

public AudioPlayer(String currentTrack) {
this.currentTrack = currentTrack;
}

@Override
public void play() {
System.out.println("Playing audio: " + currentTrack);
}

@Override
public void pause() {
System.out.println("Pausing audio");
}

@Override
public void stop() {
System.out.println("Stopping audio");
}
}

public class VideoRecorder implements MediaRecorder {
private String currentRecording;

public VideoRecorder(String currentRecording) {
this.currentRecording = currentRecording;
}

@Override
public void record() {
System.out.println("Recording video: " + currentRecording);
}

@Override
public void pauseRecording() {
System.out.println("Pausing video recording");
}

@Override
public void stopRecording() {
System.out.println("Stopping video recording");
}
}

Quản Lý Hệ Thống Bảo Mật

public interface Authentication {
boolean login(String username, String password);
void logout();
}

public interface Authorization {
boolean hasPermission(String permission);
void grantPermission(String permission);
}

public class User implements Authentication, Authorization {
private String username;
private Set<String> permissions;

public User(String username) {
this.username = username;
this.permissions = new HashSet<>();
}

@Override
public boolean login(String username, String password) {
// Thực hiện đăng nhập
return true;
}

@Override
public void logout() {
System.out.println("User logged out");
}

@Override
public boolean hasPermission(String permission) {
return permissions.contains(permission);
}

@Override
public void grantPermission(String permission) {
permissions.add(permission);
System.out.println("Permission granted: " + permission);
}
}

💡 Lời khuyên: Hãy thực hành với các ví dụ thực tế để hiểu rõ hơn về cách sử dụng tính đa hình trong các tình huống khác nhau.

Tiếp Theo 🎯

Trong các bài học tiếp theo, chúng ta sẽ:

  • Tìm hiểu về encapsulation
  • Học cách sử dụng access modifiers
  • Thực hành với các ví dụ thực tế
  • Tìm hiểu về design patterns