【问题标题】:Polymorphism - Method overriding and overloading not clear多态性 - 方法覆盖和重载不清楚
【发布时间】:2019-09-26 16:59:33
【问题描述】:

我正在学习多态性,但无法理解它是如何工作的

当我尝试创建对象Car car = new Audi(); 时,覆盖打印“这是奥迪”。但是对于相同的对象,我无法调用Audi 类的first(int x, int y)... 我只能调用Carfirst()

Overriding 打印 Audi 方法,Overloading 打印 Car 方法.. 使用相同对象调用时..

类车

class Car {
   public void carName() {
      System.out.println("Parent of car");
   }

   public int first() {
      System.out.println("Base - Parent");
      return 2;
   }
}

宝马级

class BMW extends Car {
   public void carName() {
      System.out.println("This is BMW");
   }
   public int first(int x) {
      System.out.println("BMW override");
      return x;
   }
}

奥迪级

class Audi extends BMW {
   public void carName() {
      System.out.println("This is Audi");
   }
   public int first(int x, int y) {
      System.out.println("AUdi Override");
      return x;
   }
}

类PloyMor

public class PolyMor extends Audi {
   public static void main(String args[]) {
      Car car = new Audi();
      car.carName();
      car.first();
   }
}

【问题讨论】:

  • 为什么奥迪扩展宝马而不是汽车?
  • 方法first()first(int, int) 是完全不同的、不相关的方法。对于编译器来说,它们具有相同的名称几乎是无关紧要的。而且,由于您在 Car 上没有 first(int, int) 方法,因此当使用您声明为 Car 的对象时,唯一可用的方法是无参数版本。
  • @OldProgrammer 我也试过了..但输出仍然相同..即使奥迪扩展汽车,汽车对象也会打印奥迪类 carName() 方法但无法调用方法重载..仍然只能调用 Car 的 first() 方法..
  • @resueman 哦,好吧,我想我慢慢来了……谢谢!
  • Audi 扩展 BMW 没有意义,您正在使用 first(int x, int y) 重载 first() 方法,并且它是在特定车型中定义的,Car 本身没有该方法。

标签: java


【解决方案1】:

重要提示:我假设 BTW 类扩展 Car 而不是 Audi(这在 IMO 中毫无意义)。


但是对于同一个对象,我无法调用奥迪类的 first(int x, int y)。

你需要区分变量类型和(对象)类型。如果是

Car car = new Audi();

变量类型是Car,而它持有的对象类型是Audi

您需要意识到编译器不会假设变量的值是什么。它应用相同的规则,就好像它是方法的参数一样

void someMethod(Car car){
    //do something with `car`
}

在该方法的内部,我们不知道它是否会与someMethod(new Audi());someMethod(new BMW()); 一起使用。

那么,哪些方法可以通过someMethod 主体内的car 变量安全 调用?只有那些保证会在所有对象中实现(出现),这些对象可以用作方法参数。如果该方法允许我们编写car.first(1, 2);,它将适用于someMethod(new Audi()) 这样的场景,但对于someMethod(new BMW()) 将失败,因为BMW 没有first(int x, int y) 方法。

【讨论】:

    【解决方案2】:

    如果您在基类中定义了另一个方法,如下所示:

    public int first(int a, int b) {
        System.out.println("Base - Parent");
        return 2;
    }
    

    由于您尝试创建的最终对象是Car 类的对象,它只有Car 类中的方法,如果存在于Audi 类中,将覆盖Car 中的方法类。

    【讨论】:

      【解决方案3】:

      调用方法取决于编译类型而不是运行时类型。

      Car car = new Audi();
      ^               ^
      compile-type    runtime type
      

      编译类型与运行时类型: Source

      信用:@duffymo

      假设我们有

      A test = new B();
      
      • 在编译时:编译器只知道变量test的类型是A。他不知道我们实际上给了他一个B的实例。因此test的编译类型是A。

      • 在运行时:已知测试类型为 B,因此运行时类型为 B

      由于编译器不知道运行时会存储什么类型,它只允许我们调用A类的方法

      解决方案:

      如果您想从实例化类型调用方法,请执行此操作 那么你就可以访问方法first(int x, int y)

      Audi car = new Audi();
      car.carName();
      car.first(); // Original Method
      car.first(3, 3); // Overloading
      

      输出:

      This is Audi
      Base - Parent
      AUdi Overload
      

      P.S 就像 OldProgrammer 提到的奥迪应该扩展 Car 而不是 BMW

      【讨论】:

      • 我会使用术语“编译类型”和“运行时”类型。编译类型是 Car;汽车引用的运行时类型是奥迪。
      【解决方案4】:

      您不是首先从Car 覆盖Audi,因为签名不同。

      签名包括方法名、参数和 throws 子句。

      来自Car 的方法first() 不接受任何参数。

      Audi 中,它需要两个整数作为参数。不一样。

      即使是简单的层次结构也不是一个好的设计。您遇到问题是因为您的实施很糟糕。

      试试这个:

      public abstract class Car {
          private String name;
          private int id;
      
          public Car(String name, int id) { 
              this.name = name;
              this.id = id;
          }
      
          public String getName() { return this.name; }
          public int getId() { return this.id; }
      
          public static void main(String [] args) {
              List<Car> cars = new ArrayList<>();
              cars.add(new Audi());
              cars.add(new Bmw());
              System.out.println(cars);
          }
      }
      
      class Audi extends Car {
          public Audi() {
              super("Audi", 1);
          }
      }
      
      class Bmw extends Car {
          public Bmw() {
             super("BMW", 2);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-06-26
        • 1970-01-01
        • 2010-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-08
        相关资源
        最近更新 更多