Overriding vs Overloading
Vấn đề
Phần tiêu đề “Vấn đề”“Overriding” và “Overloading” nghe rất giống nhau, và cả hai đều liên quan đến “nhiều phương thức cùng tên” - dễ nhầm lẫn, đặc biệt khi mắc lỗi tưởng đang override nhưng thực ra đã vô tình overload:
public class Animal { void makeSound(String volume) { // makeSound(String) System.out.println("Âm thanh mức " + volume); }}
public class Dog extends Animal { @Override void makeSound(int volume) { // makeSound(int) - KHÁC tham số với Animal! System.out.println("Gâu gâu mức " + volume); }}Ở đây, @Override sẽ báo lỗi biên dịch - vì Dog.makeSound(int) không thực sự override Animal.makeSound(String) (khác kiểu tham số), nó chỉ tạo ra một overload mới hoàn toàn, không liên quan gì đến phương thức của Animal. Nhờ @Override, lỗi được phát hiện ngay - nhưng nếu không dùng @Override, code này vẫn biên dịch được (chỉ là tạo ra một method overloading không mong muốn), và lỗi logic sẽ ẩn náu rất khó phát hiện.
Bảng phân biệt
Phần tiêu đề “Bảng phân biệt”| Overloading | Overriding | |
|---|---|---|
| Vị trí | Cùng một class | Lớp con định nghĩa lại phương thức của lớp cha |
| Danh sách tham số | Phải khác nhau | Phải giống hệt nhau |
| Kiểu trả về | Có thể khác (miễn tham số khác) | Phải giống hoặc là kiểu con (covariant return type) |
| Xác định lúc nào | Lúc biên dịch (compile-time), dựa vào kiểu đối số | Lúc chạy chương trình (runtime), dựa vào lớp thực sự của đối tượng |
| Liên quan đến đa hình? | Không | Có - nền tảng của runtime polymorphism |
Ví dụ minh họa rõ sự khác biệt
Phần tiêu đề “Ví dụ minh họa rõ sự khác biệt”public class Calculator { // OVERLOADING - cùng tên "add", khác tham số, cùng trong Calculator int add(int a, int b) { return a + b; } double add(double a, double b) { return a + b; }}
public class Animal { void eat() { System.out.println("Animal đang ăn"); }}
public class Dog extends Animal { @Override // OVERRIDING - cùng tên "eat", CÙNG tham số (không có), lớp con định nghĩa lại void eat() { System.out.println("Dog đang ăn nhanh"); }}Giải pháp / Cách dùng đúng
Phần tiêu đề “Giải pháp / Cách dùng đúng”- Luôn dùng
@Overridekhi có ý định ghi đè phương thức của lớp cha - trình biên dịch sẽ báo lỗi ngay nếu chữ ký không khớp, thay vì âm thầm tạo ra một overload không mong muốn - Khi thiết kế API, tránh tạo quá nhiều overload dễ gây nhầm lẫn cho người gọi (ví dụ nhiều overload với tham số cùng kiểu nhưng thứ tự khác nhau)
Tóm tắt
Phần tiêu đề “Tóm tắt”Overloading: nhiều phương thức cùng tên, khác tham số, trong cùng một lớp - quyết định lúc biên dịch. Overriding: lớp con định nghĩa lại phương thức của lớp cha với chữ ký giống hệt - quyết định lúc chạy chương trình, nền tảng của đa hình.
- Luôn dùng
@Overrideđể trình biên dịch xác nhận bạn đang thực sự override, không phải vô tình overload