Trong Java, overriding (đè phương thức) và overloading (nạp phương thức) là hai khái niệm quan trọng trong lập trình hướng đối tượng. Chúng cho phép các lập trình viên thiết kế và sử dụng các phương thức linh hoạt hơn. Dưới đây là giải thích chi tiết về từng khái niệm và mục đích sử dụng của chúng.
1. Overriding (Đè phương thức)
Khái niệm: Overriding là quá trình mà một lớp con (subclass) cung cấp một cài đặt cụ thể cho một phương thức đã được định nghĩa trong lớp cha (superclass) của nó.
Đặc điểm:
- Phương thức trong lớp con phải có cùng tên, kiểu trả về (return type) và danh sách tham số (parameter list) như phương thức trong lớp cha.
- Sử dụng từ khóa
@Override
để ghi chú rằng bạn đang ghi đè một phương thức.
Mục đích sử dụng:
- Tính mở rộng (Extension): Cho phép lớp con tùy chỉnh hoặc thay đổi hành vi của phương thức mà nó kế thừa từ lớp cha.
- Tính đa hình (Polymorphism): Giúp đạt được đa hình động, cho phép gọi phương thức của lớp con thông qua tham chiếu của lớp cha. Điều này có nghĩa là cùng một phương thức có thể hoạt động khác nhau dựa trên đối tượng cụ thể.
Ví dụ:
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
}
}
// Sử dụng
Animal myDog = new Dog();
myDog.sound(); // In ra: Dog barks
2. Overloading (Nạp phương thức)
Khái niệm: Overloading là quá trình định nghĩa nhiều phương thức trong cùng một lớp với cùng một tên nhưng có các tham số khác nhau (số lượng, loại hoặc thứ tự).
Đặc điểm:
- Các phương thức có thể có kiểu trả về khác nhau, nhưng điều này không phải là điều kiện bắt buộc.
- Phương thức phải khác nhau về danh sách tham số.
Mục đích sử dụng:
- Tăng tính linh hoạt: Cho phép bạn gọi cùng một phương thức với các tham số khác nhau mà không cần phải tạo nhiều tên khác nhau.
- Giảm thiểu lỗi: Giúp giảm thiểu sự nhầm lẫn cho lập trình viên vì họ không cần phải nhớ nhiều tên phương thức.
Ví dụ:
class MathUtil {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
}
// Sử dụng
MathUtil math = new MathUtil();
System.out.println(math.add(5, 10)); // In ra: 15
System.out.println(math.add(5.5, 10.5)); // In ra: 16.0
System.out.println(math.add(1, 2, 3)); // In ra: 6
Tóm tắt
- Overriding cho phép một lớp con định nghĩa lại hành vi của phương thức mà nó kế thừa từ lớp cha, nhằm mục đích tùy chỉnh hành vi của lớp.
- Overloading cho phép định nghĩa nhiều phương thức cùng tên nhưng với các tham số khác nhau trong cùng một lớp, nhằm tăng tính linh hoạt và khả năng sử dụng.
Hai khái niệm này đóng vai trò quan trọng trong việc thiết kế ứng dụng theo hướng đối tượng và tối ưu hóa mã nguồn.