1. Ghi đè phương thức (method overriding) trong Java là gì?
Trong Java, khi lớp con kế thừa từ lớp cha, lớp con sẽ kế thừa những thuộc tính và phương thức của lớp cha. Nhưng lớp con sẽ kế thừa được những gì từ lớp cha? Các bạn có thể đọc lại bài Tính kế thừa (inheritance) trong Java để nắm rõ vấn đề này.
Còn trong bài này, chúng sẽ tìm hiểu hiện tượng mà một phương thức giống nhau được định nghĩa trong cả lớp cha và lớp con. Hiện tượng này gọi là ghi đè phương thức (method overriding) trong Java.
Lưu ý: Nhiều bạn nhầm lẫn giữa nạp chồng (overloading) và ghi đè (overriding). Các bạn có thể đọc lại bài Xây dựng lớp trong Java với nạp chồng (overloading) và kết tập (aggregation) để hiểu rõ về nạp chồng (overloading).
2. Một ví dụ về ghi đè phương thức (method overriding)
class LopCha{
public void xuat(){
System.out.println("Lop cha.");
}
}
class LopCon extends LopCha{
@Override
public void xuat(){
System.out.println("Lop con.");
}
}
public class Test{
public static void main(String[] args) {
LopCon aaa = new LopCon();
aaa.xuat();
}
}
Kết quả
Lop con.
Trong ví dụ trên, hàm xuat()
được định nghĩa trong cả lớp cha LopCha và lớp con LopCon. Khi đối tượng aaa của lớp LopCon gọi hàm xuat()
thì hàm xuat()
được ghi đè (overriding) bên trong lớp LopCon được gọi.
Lưu ý: Annotation @Override
được sử dụng trong ví dụ trên. Trong Java, annotation là metadata giúp cung cấp thông tin cho trình biên dịch. Annotation @Override
báo với trình biên dịch là phương thức đã được ghi đè (overriding) từ lớp cha.
Chương trình không bắt buộc sử dụng annotation @Override
. Nhưng khi đã sử dụng thì phải tuân thủ các quy tắc overriding nếu không trình biên dịch sẽ báo lỗi.
3. Các quy tắc ghi đè (overriding)
Lớp con và lớp cha phải có phương thức giống nhau: giống tên phương thức, kiểu dữ liệu trả về và danh sách tham số.
Chúng ta không thể ghi đè (overriding) những phương thức final và static.
Lớp con phải luôn luôn ghi đè (overriding) phương thức abstract của lớp cha.
4. Sử dụng từ khóa super với overriding trong Java
Chúng ta có thể gọi phương thức của lớp cha trong lớp con sau khi đã ghi đè (overriding) phương thức đó bằng cách sử dụng từ khóa super.
class LopCha{
public void xuat(){
System.out.println("Lop cha.");
}
}
class LopCon extends LopCha{
@Override
public void xuat(){
super.xuat();//gọi hàm xuat() của lớp cha
System.out.println("Lop con.");
}
}
public class Test{
public static void main(String[] args) {
LopCon aaa = new LopCon();
aaa.xuat();
}
}
Kết quả
Lop cha.
Lop con.
5. Access modifier với ghi đè phương thức (method overriding)
Phương thức được ghi đè ở lớp con có thể có access modifier khác với lớp cha. Nhưng access modifier này phải có phạm truy truy cập lớn hơn của lớp cha. Ví dụ, một phương thức myClass()
trong lớp cha khai báo là protected. Phương thức myClass()
trong lớp con chỉ có thể là public hoặc protected chứ không thể khai báo là private.
class LopCha{
protected void xuat(){//hàm protected
System.out.println("Lop cha.");
}
}
class LopCon extends LopCha{
@Override
public void xuat(){//hàm ghi đè public
System.out.println("Lop con.");
}
}
public class Test{
public static void main(String[] args) {
LopCon aaa = new LopCon();
aaa.xuat();
}
}
Kết quả
Lop con.
Trong ví dụ trên, lớp cha LopCha có phương thức xuat()
là protected. Lớp con LopCon ghi đè phương thức xuat()
khai báo là public.