Bỏ qua để đến nội dung

Overriding vs Overloading

“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.

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
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"); }
}
  • Luôn dùng @Override khi 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)

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