【问题标题】:Inheritance in Java, apparent type vs actual typeJava中的继承,表观类型与实际类型
【发布时间】:2015-08-22 06:16:12
【问题描述】:

谁能解释一下这次执行的结果?我不知道为什么调用每个方法。以及我们如何区分真实类型与表观类型。谢谢:)

public class JavaApplication15 {
   public static void main(String[] args) {
       A a = new A();
       B b= new B();
       A ab = new B();
       b.f(a);
       b.f(b);
       b.f(ab);
  }  
}

public class A {
   private final String id="A";
   public void f(A x){
     System.out.println("Send a fax to "+ x ) ;
  }
  public String toString(){return id;}
}

public class B extends A{
   private final String id="B";
   public void f(B x){
     System.out.println("Send an email to"+ x ) ;
   }
   public String toString(){return id;}
}

结果:

Send a fax to A
Send an email to B
Send a fax to B

【问题讨论】:

    标签: java inheritance types extends


    【解决方案1】:

    你是overloading,它(根据维基百科)创建了具有不同实现的多个同名方法。我认为您的意思是 override f(A x) 方法和 f(B x) 方法。覆盖(根据维基百科)允许子类或子类提供已由其超类或父类之一提供的方法的特定实现

    基于您问题中表达的惊讶,我认为您想要类似的东西

    @Override
    public void f(A x) {
      System.out.println("Send an email to"+ x ) ;
    }
    

    【讨论】:

      【解决方案2】:
      @Override
      public String toString()
      {
          return id;
      }
      

      这定义了类的输出方式。当你调用如下函数时:

      b.f(a)
      

      您正在输入一个类作为参数。由于您的toString() 方法是输出类的标准方法的替代方法,因此您在Send an email to 之后显示id

      【讨论】:

        【解决方案3】:

        因为 B 扩展了 A 并且 A 有一个公共方法。所以它有以下两种方法 -

        public void f(A x){
             System.out.println("Send a fax to "+ x ) ;
        } 
        

        还有——

        public void f(B x){
             System.out.println("Send an email to"+ x ) ;
        }
        

        实际上B 中的第二个方法是继承自A 的方法void f(A x) 的重载版本

        【讨论】:

          【解决方案4】:

          B 类的对象同时具有f(A)f(B)。当您调用f(x) 时,它通常会选择与x 的类型匹配的最具体的一个。为此,重要的是 reference 的类型。

          所以你的aA,因此它调用f(A)。您的bB,因此它调用f(B)。但是你的ab 是什么?引用的类型是A。所以编译器告诉它调用f(A)重载。

          但是,它不应该使用ab 对象作为A 并因此使用A.toString() 而不是B.toString() 打印send a fax to A

          不,因为在这种情况下要调用的方法的选择不是由参数决定的。它不是像上面的选择那样在重载之间进行选择,而是在覆盖之间进行选择。在决定使用哪种方法时,一个来自超类还是一个来自子类,对象的实际类型决定了它。由于ab 所指的对象实际上是B,因此选择BtoString()

          所以-在重载方法中,选择的方法是根据参数的数量和类型确定的,参数的类型是引用的类型。

          重写方法中,选择的是对象实例的实际类型中的那个,而不管调用它的引用类型是什么。

          请注意,只有与父方法具有相同名称、参数数量和相应参数类型的方法才被视为被覆盖

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-10-11
            • 1970-01-01
            • 1970-01-01
            • 2011-08-17
            • 2015-07-04
            • 1970-01-01
            • 2010-11-08
            相关资源
            最近更新 更多