Lio*_*ion 5 java oop polymorphism
维基百科将虚拟方法定义为:
在面向对象的编程中,虚函数或虚方法是一种函数或方法,其行为可以通过具有相同签名的函数在继承类中被覆盖[以提供多态行为].
根据定义,除了 final方法和私有方法之外,Java中的每个非静态方法都是默认的虚拟方法.不能为多态行为继承的方法不是虚方法.
Java中的静态方法永远不能被覆盖; 因此,在Java中将静态方法声明为final是没有意义的,因为静态方法本身就像最终方法一样.它们可以通过具有相同签名的方法隐藏在子类中.显然是这样,因为静态方法永远不会有多态行为:被覆盖的方法必须实现多态,而静态方法则不然.
从前一段开始,可以推动一个重要的结论.默认情况下,C++中的所有方法都是静态的,因为除非在超类中显式声明为虚拟,否则C++中的任何方法都不能以多态方式运行.相比之下,除了final,static和private方法之外,Java中的所有方法都默认是虚拟的,因为它们默认具有多态行为(不需要在Java中将方法显式声明为虚拟,因此,Java没有像"virtual"这样的关键字).
现在,让我们演示实例变量(静态)也不能通过Java中的以下简单示例进行多态操作.
class Super
{
public int a=5;
public int show()
{
System.out.print("Super method called a = ");
return a;
}
}
Run Code Online (Sandbox Code Playgroud)
final class Child extends Super
{
public int a=6;
@Override
public int show()
{
System.out.print("Child method called a = ");
return a;
}
}
Run Code Online (Sandbox Code Playgroud)
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());
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码片段产生的输出如下.
s.a = 5 c.a = 6 Child method called a = 6 Child method called a = 6
在这个例子中,两个呼叫s.show()和c.show()到由show()通过型的变量方法Super和类型的Child,分别调用show()的方法中Child类.这意味着,show()在该方法中Child类覆盖了show()在该方法Super的类,因为它们两者具有相同的签名.
但是,这不能应用于a在两个类中声明的实例变量.在这种情况下,s.a要提到a的Super类和显示5和c.a将提及a在Child类和显示6意味着a在Child类只是隐藏(以及如发生在非静态方法不覆盖)a在Super类.
经过长时间的讨论,只有一个问题.为什么实例变量(以及其余变量)没有被覆盖?实施这种机制的特殊原因是什么?如果它们被覆盖了,会有任何优点或缺点吗?
我认为重写的目的是在不改变签名的情况下改变功能。这仅与方法相关:方法可能具有相同的签名但具有不同的行为。字段只有“签名”,也仅限于类型和名称。它们没有行为,所以没有什么可以被覆盖。
无法“覆盖”字段的其他原因是字段通常是私有的(或应该是私有的),因此它们实际上是类实现的血淋淋的细节。然而,方法代表类的外部接口。该外部接口应该支持多态,以便更容易地更改模块的功能而不更改模块之间的关系。