Почему мы используем интерфейсные ссылочные типы в Java? - PullRequest
6 голосов
/ 10 июля 2011

Я собираюсь сдать выпускной экзамен в своем самом первом классе объектно-ориентированного программирования, и я до сих пор не понимаю кое-что о концепции полиморфизма.

Допустим, у меня есть абстрактный класс "Автомобиль""и этот класс имеет один подкласс под названием" Самолет ".У меня вопрос, в чем разница между этими двумя кодами?

Aircraft Jetplane = new Aircraft();

и

Vehicle Jetplane = new Aircraft();

Ответы [ 7 ]

14 голосов
/ 10 июля 2011

Во втором, тогда Jetplane может быть чем-то еще, что наследует от Vehicle, а не только от Aircraft. Например, у вас может быть что-то вроде

Vehicle veh = null;
if (someCondition)
    veh = new Aircraft();
else
    veh = new Boat();

Это невозможно сделать в первом примере, потому что Лодка - это не Самолет.

5 голосов
/ 10 июля 2011

Первый не является полиморфным: оба типа реактивного самолета во время компиляции и во время выполнения - Aircraft.

Второй - полиморфный.Тип самолета во время компиляции - Vehicle, но тип времени выполнения - Aircraft.

3 голосов
/ 11 июля 2011

Как сказал Мерлин, для объяснения полиморфизма требуется длинная глава, но позвольте мне попытаться объяснить на простом примере.

Допустим, вас попросили переместить реактивный самолет и лодку и проверить, сдвинулся ли каждый из них. Тогда вы могли бы сделать это:

Aircraft jetPlane = new Aircraft();
jetPlane.moveForward();
boolean movementStatus = jetPlane.didItMoveForward();

Boat boat = new Boat();
boat.moveForward();
boolean movementStatus = boat.didItMoveForward();

Или это

boolean moveIt(Aircraft plane) {
    plane.moveForward();
    boolean movementStatus = jetPlane.didItMoveForward();
    return movementStatus;
}
....
Aircraft jetPlane = new Aircraft();
boolean status = moveIt(jetPlane);
....
boolean moveIt(Boat boat) {
    boat.moveForward();
    boolean movementStatus = boat.didItMoveForward();
    return movementStatus;
}
....
Boat boat = new Boat();
status = moveIt(boat);

Теперь, как вы можете видеть выше, вы должны определить конкретный метод для каждого типа транспортного средства. Это приведет к дублированию кода, и этот код нельзя использовать повторно. Вот где проявляется полиморфизм.

Допустим, у вас был такой метод:

boolean moveIt(Vehicle vehicle) {
    vehicle.moveForward();
    boolean movementStatus = vehicle.didItMoveForward();
    return movementStatus;
}

Aircraft jetPlane = new Aircraft();
boolean status = moveIt(jetPlane);

Boat boat = new Boat();
status = moveIt(boat);

Как вы можете видеть выше, из-за полиморфной природы экземпляров транспортного средства (самолет и лодка), один метод moveIt достаточен для хорошего повторного использования логики.

HTH, K

3 голосов
/ 10 июля 2011

Вторая вещь также происходит.Тип переменной определяет, какие методы являются видимыми.Вы можете объявить переменные типа интерфейса или любого (включая абстрактный класс) типа.Вы можете создавать только объекты конкретного (неабстрактного) класса.

Если ваша переменная имеет тип интерфейса, все методы, объявленные в интерфейсе, являются видимыми.Если это тип класса, то же самое также верно.

Однако объект отвечает за выполнение фактической работы в методе.Таким образом, вызов метода «делегируется» объекту.

Если ваша переменная имеет слишком общий тип, нужные вам методы не будут видны.Если он слишком конкретен, вы не сможете указать все переменные, которые вам могут понадобиться.Это компромисс.

1 голос
/ 10 апреля 2018

Согласно ORACLE doc:

Использование интерфейса в качестве типа Когда вы определяете новый интерфейс, вы определяете новый тип эталонных данных.Имена интерфейсов можно использовать везде, где вы можете использовать любое другое имя типа данных.Если вы определяете ссылочную переменную, тип которой является интерфейсом, любой объект, который вы ей назначаете, должен быть экземпляром класса, который реализует интерфейс.

В качестве примера, вот метод для поиска самого большого объекта впара объектов для любых объектов, которые создаются из класса, который реализует Relatable:

public Object findLargest(Object object1, Object object2) {
   Relatable obj1 = (Relatable)object1;
   Relatable obj2 = (Relatable)object2;
   if ((obj1).isLargerThan(obj2) > 0)
      return object1;
   else 
      return object2;
}

Приведя object1 к типу Relatable, он может вызвать метод isLargerThan.

Если выЧтобы реализовать Relatable во множестве классов, объекты, созданные из любого из этих классов, можно сравнить с методом findLargest () при условии, что оба объекта принадлежат одному и тому же классу.Точно так же их все можно сравнить с помощью следующих методов:

public Object findSmallest(Object object1, Object object2) {
   Relatable obj1 = (Relatable)object1;
   Relatable obj2 = (Relatable)object2;
   if ((obj1).isLargerThan(obj2) < 0)
      return object1;
   else 
      return object2;
}

public boolean isEqual(Object object1, Object object2) {
   Relatable obj1 = (Relatable)object1;
   Relatable obj2 = (Relatable)object2;
   if ( (obj1).isLargerThan(obj2) == 0)
      return true;
   else 
      return false;
}

Эти методы работают для любых «связанных» объектов, независимо от их наследования классов.Когда они реализуют Relatable, они могут иметь как собственный тип класса (или суперкласса), так и тип Relatable.Это дает им некоторые преимущества множественного наследования, когда они могут работать как с суперклассом, так и с интерфейсом.

0 голосов
/ 11 июля 2011

Первый случай:

jetPlane - это object of Aircraft Class.И может использовать все атрибуты и методы класса самолетов.

Второй случай:

jetPlane is not an object.Это reference to object of Aircraft Class.Даже при том, что это было создано, используя конструктор класса Авиации, это может only see and use the methods and attributes of the Vehicle Class and not the Aircraft class.

0 голосов
/ 11 июля 2011

второй использует преимущества полиморфизма ... хотя полиморфизм иногда более выгоден с массивом или списком ... просто представьте, что у вас есть несколько классов, которые наследуются от транспортного средства, скажем, самолет, автомобиль и велосипед, и у вас есть массивобъекты этого класса.Может быть, в какой-то момент в вашей программе вам может понадобиться замедлить работу всего транспортного средства ... если ранее вы объявили массив транспортных средств, например: Vehicle array = new Vehicle [10];вы можете просто сделать для Vehicle v в массиве: v.slowDown () и метод slowDown из класса Car будет вызываться, если в массиве есть объект car, будет также вызываться slowDown из Plane, еслисамолет и так далее ...

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