Wikipedia định nghĩa virtual methods như:Các phương thức trong mô hình hướng đối tượng có thể bị ghi đè bởi các phương thức có cùng chữ ký trong các lớp kế thừa. Tuy nhiên, các biến không thể. Tại sao?
Trong lập trình hướng đối tượng, một hàm ảo hoặc một phương pháp ảo là một chức năng hoặc các phương pháp mà hành vi có thể được ghi đè trong một lớp kế thừa của một hàm với cùng một chữ ký [để cung cấp một hành vi đa hình].
Theo định nghĩa, mọi phương pháp không tĩnh trong Java là theo mặc định ảo mặc định trừ phương pháp cuối cùng và riêng tư. Phương thức không thể kế thừa cho hành vi đa hình là không phải là một phương pháp ảo.
Phương pháp tĩnh trong Java không bao giờ bị ghi đè; do đó, nó là vô nghĩa để khai báo một phương thức tĩnh là cuối cùng trong Java bởi vì các phương thức tĩnh tự hành xử giống như các phương thức cuối cùng. Chúng có thể chỉ đơn giản là ẩn trong các lớp con theo các phương thức có cùng chữ ký. Rõ ràng là vì các phương thức tĩnh không bao giờ có hành vi đa hình: một phương thức được ghi đè phải đạt được tính đa hình, mà không phải là trường hợp với các phương thức tĩnh.
Từ đoạn trên, một kết luận quan trọng có thể được thúc đẩy. Tất cả các phương thức trong C++ là mặc định tĩnh vì không có phương thức nào trong C++ có thể hoạt động đa hình cho đến khi và trừ khi chúng được khai báo một cách rõ ràng trong lớp siêu. Ngược lại, tất cả các phương thức trong Java ngoại trừ các phương thức cuối cùng, tĩnh và riêng là mặc định ảo vì chúng có hành vi đa hình theo mặc định (không cần khai báo một cách rõ ràng các phương thức như ảo trong Java và, do đó, Java không có từ khóa nào như "ảo").
Bây giờ, hãy chứng minh rằng các biến mẫu (tĩnh quá) không thể hoạt động đa hình từ ví dụ đơn giản sau đây trong Java.
class Super
{
public int a=5;
public int show()
{
System.out.print("Super method called a = ");
return a;
}
}
final class Child extends Super
{
public int a=6;
@Override
public int show()
{
System.out.print("Child method called a = ");
return a;
}
}
final public class Main
{
public static void main(String...args)
{
Super s = new Child();
Child c = new Child();
System.out.println("s.a = "+s.a);
System.out.println("c.a = "+c.a);
System.out.println(s.show());
System.out.println(c.show());
}
}
Sản lượng sản xuất bởi các đoạn mã trên là như sau.
s.a = 5 c.a = 6 Child method called a = 6 Child method called a = 6
Trong ví dụ này, cả hai gọi s.show()
và c.show()
thực hiện cho các phương pháp show()
thông qua các biến kiểu Super
và kiểu Child
, tương ứng, gọi phương thức show()
trong lớp Child
. Điều này có nghĩa là phương thức show()
trong lớp Child
ghi đè phương thức show()
trong lớp Super
vì cả hai đều có chữ ký giống hệt nhau.
Điều này, tuy nhiên, không thể áp dụng cho biến mẫu a
được khai báo trong cả hai lớp.Trong trường hợp này, s.a
sẽ tham khảo a
trong lớp Super
và hiển thị 5
và c.a
sẽ tham khảo a
trong lớp Child
và hiển thị 6
nghĩa là a
trong Child
lớp chỉ da (và không ghi đè như đã xảy ra để không tĩnh phương pháp) a
trong lớp Super
.
Sau cuộc thảo luận dài này, chỉ có một câu hỏi. Tại sao các biến mẫu (và các biến còn lại) không bị ghi đè? Những lý do đặc biệt để thực hiện một cơ chế như vậy là gì? Liệu có bất kỳ ưu điểm hay nhược điểm nào, nếu chúng bị ghi đè?
C++ phương pháp không ảo không tĩnh. chúng là các phương thức thể hiện không thể bị ghi đè. Chúng tương tự như các phương thức cuối cùng trong Java: các phương thức mẫu không thể bị ghi đè. –
'Theo đoạn trên, một kết luận quan trọng có thể được thúc đẩy. Tất cả các phương thức trong C++ (mặc định trong C) là mặc định tĩnh vì không có phương thức nào trong C++ có thể hoạt động đa hình cho đến khi và trừ khi chúng được khai báo một cách rõ ràng trong cơ sở ': một phương thức tĩnh không thể truy cập đối tượng [no' this' cho các phương thức này ] trong khi một chức năng [mặc định] không ảo trong C++ có thể – amit
Tôi điều từ "ghi đè" không được áp dụng cho các biến. Bạn ghi đè hành vi, nhưng không phải là trạng thái. Các biến có thể được truy cập từ lớp con, vì vậy không cần phải "ghi đè lên" (bạn có thể thay đổi giá trị của nó và nó có cùng tên). Ngoài ra còn có một cái gì đó gọi là shadowing, vì vậy nếu bạn redeclare một biến với cùng tên nó là một biến khác nhau trong thời gian chạy. –