Полиморфизм. Метод переопределения и перегрузки не ясен - PullRequest
0 голосов
/ 26 сентября 2019

Я изучаю полиморфизм, но не могу понять, как он работает

Когда я пытаюсь создать объект Car car = new Audi();, переопределяется печать «Это Audi».Но с одним и тем же объектом я не могу вызвать first(int x, int y) класса Audi ... Я могу вызвать только Car класс first().

Переопределение печати методом Audi, Перегрузка печати автомобиляметод .. при вызове с тем же объектом ..

Класс Car

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

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

Класс BMW

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;
   }
}

Класс Audi

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();
   }
}

Ответы [ 4 ]

2 голосов
/ 26 сентября 2019

Важно: я предполагаю, что класс BTW расширяется Car, а не Audi (что не имеет смысла ИМО).


Но с тем же объектом я не могуДля вызова первого (int x, int y) класса Audi.

Необходимо различать тип переменной и тип значения (объект).В случае

Car car = new Audi();

тип переменной равен Car, а тип объекта, который она содержит, - Audi.

Вы должны понимать, что компилятор не принимает значение переменной.Он применяет те же правила, как если бы он был параметром метода, например

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

, где внутри этого метода мы не знаем, будет ли он использоваться с someMethod(new Audi()); или someMethod(new BMW());.

* 1030.* Так какие методы могут быть безопасно вызваны через car переменную внутри someMethod тела?Только те, которые гарантируют , будут реализованы (появиться) в всех объектах, которые могут быть использованы в качестве аргументов метода.Если этот метод позволит нам написать car.first(1, 2);, он будет работать для сценария, подобного someMethod(new Audi()), но потерпит неудачу для someMethod(new BMW()), потому что у BMW нет метода first(int x, int y).
1 голос
/ 26 сентября 2019

Вы не переопределяете сначала из Car в Audi, потому что подписи разные.

Подпись включает имя метода, параметры и предложение throws.

Метод first() из Car не имеет аргументов.

В 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);
    }
}
1 голос
/ 26 сентября 2019

Это сработало бы, если бы в базовом классе был определен другой метод, подобный следующему:

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

Поскольку конечный объект, который вы пытаетесь создать, является объектом класса Car, он имеет толькометоды класса Car, которые, если присутствуют в классе Audi, будут переопределять методы класса Car.

1 голос
/ 26 сентября 2019

Вызов метода зависит от типа компиляции, а не от типа среды выполнения.

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

Тип компилирования против типа среды выполнения: Источник

Кредит: @ duffymo

Допустим, у нас есть

A test = new B();
  • во время компиляции: компилятор знает только, что переменная test имеет тип A. Онне знает, что мы на самом деле даем ему экземпляр B. Поэтому тип теста при компиляции - 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

PS Как упомянул OldProgrammer, Audi должна расширить автомобиль вместо BMW

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...