Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 方法重写。为什么这个程序不调用子类方法?_Java - Fatal编程技术网

Java 方法重写。为什么这个程序不调用子类方法?

Java 方法重写。为什么这个程序不调用子类方法?,java,Java,为什么这个程序不调用子类方法?它背后的概念是什么?我完全不明白这一点。 下面是代码 超级级 public class TV { public void checkType(TV b) { System.out.println("Its a TV"); } } 儿童班 public class LedTv extends TV { public void checkType(LedTv b) { System.out.prin

为什么这个程序不调用子类方法?它背后的概念是什么?我完全不明白这一点。 下面是代码

超级级

public class TV {

     public void checkType(TV b) {
          System.out.println("Its a TV");
     }
}
儿童班

public class LedTv extends TV {

    public void checkType(LedTv b) {
         System.out.println("Its a LED TV");
    }

}
测试用例以获得结果

public class TestTV {

    public static void main(String argss[]) {
         TV a = new TV();
         TV b = new LedTv();
         a.checkType(a);
         b.checkType(b);

    }
}
两个checkType方法都会打印

Its a TV
Its a TV

重写方法的参数类型必须相同。如果要重写子类中的方法,它必须具有相同的参数,只有返回类型可以不同,但与超类中的相同层次结构。方法

无效检查类型(TV)
是与
无效检查类型(LedTv)
不同的函数原型

因此,您不是在重写,而是在重载


对于重写,函数名和参数类型必须相同,并且返回类型必须相关。关联性的确切定义超出了这个问题的范围。

当方法具有相同的签名时,它们会在继承过程中被重写。根据签名,签名取决于:

  • 方法名
  • 参数的数目
  • 参数的类型
  • 在你的例子中,这些方法

    public void checkType(TV b)
    public void checkType(LedTv b)
    

    很明显,由于参数的类型不同,签名也不同。得到的称为方法重载,因为两个对象都是TV类型

    TV a = new TV();
    TV b = new LedTV(); 
    
    基本上是相同的对象基类型。在创建
    b
    的情况下,您所要做的基本上就是告诉您希望超类实例也具有子类功能。您正在重载这些方法,而不是重写它们。你告诉程序如果参数是LedTV,打印这个,如果参数是TV,打印这个。您只是将
    if-else
    逻辑外包给程序本身。你所做的是

    if(TV == TV) print TV
    else if (TV == LedTV) print LedTV
    
    但问题是,在代码中,两个对象都是TV类型的,因此始终使用超类方法,第一个if为true,第二个if甚至没有计算

    将b改为:

    LedTv b = new LedTv();
    b.checkType(b);
    
    它现在可以正常工作,因为
    b
    属于
    LedTV
    类型

    public class LedTv extends TV {
        @Override //always put this here
        public void checkType() {//no need for argument
            System.out.println("Its a LED TV");
        }
    
    }
    
    从上面的示例中可以看到,我添加了一个注释@Override。虽然这不是必需的,但它会强制编译器检查并确保您实际上正在重写某些内容。如果你不是,你会得到一个错误,这有助于解决错误。我之所以去掉传递给check type的参数,是因为它是多余的。始终可以使用关键字指向当前所在的对象

    我意识到我忘了解释什么是重写和重载,所以我想这个例子会告诉你

    public class Main{
    
      public static void main(String[] args){
         new Main();
      }
    
      Main(){
         new SuperClass().method();
         new SuperClass().method(101010);
         new Subclass().method();
         new Subclass().method(595959);
      }
    
      class SuperClass{
    
         SuperClass(){
            System.out.println(this.getClass().getSimpleName());
         }
    
         public void method(){
            System.out.println("method() from SuperClass -> Calling method(int x)");
            method(0);
         }
         public void method(int x){
            System.out.print("method() from SuperClass " + x + "\n\n");
         }
      }
      class Subclass extends SuperClass{
         @Override
         public void method(int x){
            System.out.print("method() from SubClass " + x + "\n\n");
         }
      }
    
    }
    
    输出

    SuperClass
    method() from SuperClass -> Calling method(int x)
    method() from SuperClass 0
    
    SuperClass
    method() from SuperClass 101010
    
    Subclass
    method() from SuperClass -> Calling method(int x)
    method() from SubClass 0
    
    Subclass
    method() from SubClass 595959
    

    正如您在超类中所看到的那样,方法()被int重载,因为方法(intx)方法()子类中被重写。在输出中,您可以清楚地看到发生了什么

    您正在执行方法重载。对于重写父类和子类的方法签名都应相同的方法。所以在儿童班而不是这个班

    public void checkType(LedTv b) {
         System.out.println("Its a LED TV");
    }
    
    键入此项并检查-

    public void checkType(TV b) {
         System.out.println("Its a LED TV");
    }
    

    因为它没有被覆盖,所以它被重载了。您正在将
    TV
    类型的变量传递给该方法,因此它调用
    checkType(TV b)
    。但是为什么第二个checkType()方法会打印它的a TV呢?因为变量
    b
    的类型是
    TV
    ,而不是
    LedTV
    (即使它引用了这样的对象,但这并不重要).那么您是说参数在需要调用哪个方法中没有作用?@BhajjiMaga他是说您不传入对象,因为这是上下文(
    this
    )。查看您的呼叫
    a.checkType(a)
    ,其中您将给出
    a
    两次。它应该是
    a.checkType()
    ,带有这个答案中的代码。@BhajjiMaga没有必要。“this”关键字指向自身。也许你可以在上面找到其他资源。我添加了一个示例来向您展示重载和重写是如何工作的。