Java访谈后的反思:继承和多态

Mic*_*Lai 1 java polymorphism inheritance

以下代码:

class Base{}

class Agg extends Base{

   public String getFields(){
    String name="Agg";
    return name;
   }
}

public class Avf{
   public static void main(String args[]){
   Base a=new Agg();
   //please take a look here
   System.out.println(((Agg)a).getFields());  // why a needs cast to Agg? 

  }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:为什么我们不能代替 ((Agg)a).getFields()a.getFields()?为什么我们需要输入强制类型a?我提到它getFields()没有在类中定义Base,因此类Agg不会从它的基类扩展此方法.但是如果我getFields()在课堂上定义了方法 Base,比如:

class Base{
    public String getFields(){
        String name="This is from base getFields()";
        return name;
    }
}
Run Code Online (Sandbox Code Playgroud)

一切都会好的.然后 ((Agg)a).getFields()相当于a.getFields()

在代码中

Base a=new Agg();    
Run Code Online (Sandbox Code Playgroud)

这行是否a具有引用,Agg()并且可以直接调用类的方法Agg.但是,如果我没有getFields()在课程中定义方法,为什么会有区别Base?任何人都可以向我解释一下吗?

T.J*_*der 11

System.out.println(((Agg)a).getFields()); // why a needs cast to Agg?

因为Base没有一个叫做的方法getFields.

声明

Base a;
Run Code Online (Sandbox Code Playgroud)

...告诉编译器您在使用时将要使用的接口a.然后你分配new Agg();给它,你所拥有的界面a仍然是无关紧要的Base.并且由于Base没有getFields,尝试使用getFields是编译错误.

Base a=new Agg();

这行是否a具有引用,Agg()并且可以直接调用类的方法Agg.

它表示a 包含Agg对象的引用,但是该对象的接口是由Base,而不是定义的,Agg因此Agg如果它们没有被定义,你就不能调用它上面的方法Base(没有强制转换,并且强制转换是危险的,应该是尽可能避免).

如果您的代码需要访问由其定义的方法或字段Agg,则应声明变量(或我的示例中的参数)Agg a,而不是Base a.

这是关于OOP的基本原则,尤其是Java中的OOP实现:对象的接口和对象的实现之间存在很大差异.在你的例子中,你知道Base a的确是一个Agg,但请考虑这个:

void foo(Base a) {
    // Use `a` here...
}

// A long time later in a class far, far away...
xyz.foo(new Agg());
Run Code Online (Sandbox Code Playgroud)

显然,编译器不应该允许您使用a未定义的方法或字段Base.你的代码中的情况也是如此,不太明显.