Польза от полиморфизма

Когда я начал искать преимущества полиморфизма, я нашел здесь этот вопрос. Но здесь я не смог найти свой ответ. Позвольте мне рассказать, что я хочу найти. Здесь у меня есть несколько классов:

class CoolingMachines{
    public void startMachine(){
        //No implementationion
    }
    public void stopMachine(){
        //No implementationion
    }
}

class Refrigerator extends CoolingMachines{
    public void startMachine(){
        System.out.println("Refrigerator Starts");
    }
    public void stopMachine(){
        System.out.println("Refrigerator Stop");
    }
    public void trip(){
        System.out.println("Refrigerator Trip");
    }
}

class AirConditioner extends CoolingMachines{
    public void startMachine(){
        System.out.println("AC Starts");
    }
    public void stopMachine(){
        System.out.println("AC Stop");
    }
}

public class PolymorphismDemo {
    CoolingMachines cm = new Refrigerator();
    Refrigerator rf = new Refrigerator();
}

Теперь я создал два объекта в классе Demo и ссылаюсь на Refrigerator. Я полностью понял, что из объекта rf я могу вызвать метод trip() Refrigerator, но этот метод будет скрыт для объекта cm. Теперь мой вопрос заключается в том, почему я должен использовать полиморфизм или почему я должен использовать

CoolingMachines cm = new Refrigerator();

когда я в порядке с

Refrigerator rf = new Refrigerator();

Является ли эффективность полиморфных объектов хорошей или легкой по весу? Какова основная цель и разница между обоими этими объектами? Есть ли разница между cm.start(); и rf.start()?

Ответ 1

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

List<CoolingMachines> coolingMachines = ... // a list of CoolingMachines 
for (CoolingMachine current : coolingMachines) {
    current.start();
}

Или, если вы хотите разрешить метод работать с любым подклассом CoolingMachines

Ответ 2

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

Например, посмотрите Iterables в Guava - что много методов, которые (в основном) не волнует, какая реализация Iterable используется. Вы действительно хотите, чтобы весь этот код был отдельно для каждой реализации?

Где вы можете закодировать абстрактный базовый класс или интерфейс, вы позволяете себе позже использовать другие реализации, которые используют один и тот же открытый API, но могут иметь разные реализации. Даже если вам нужна только одна производственная реализация, вам может потребоваться альтернативная реализация для тестирования. (Степень, в которой это относится очень сильно зависит от рассматриваемого класса.)

Ответ 3

Поскольку позже, если вы хотите использовать AirConditioner вместо Refrigerator для охлаждения, тогда только код, который вам нужно изменить, это CoolingMachines cm = new AirConditioner();

Ответ 4

Причина, по которой вы хотите использовать

CoolingMachines cm = new Refrigerator();

заключается в том, что вы можете легко использовать другой CoolingMachines. Вам нужно только изменить эту строку кода, а остальная часть кода будет работать (поскольку она будет использовать только методы CoolingMachines, которые являются более общими, чем конкретная машина, например, Refrigerator).

Итак, для конкретного экземпляра Refrigerator вызовы cm.start(); и rf.start() работают одинаково, но cm также может быть другим объектом CoolingMachines. И этот объект может иметь другую реализацию start().

Ответ 5

Первый ответ:

Использовать полиморфизм для переопределения метода и перегрузки метода. Другие методы класса, используемые в разном классе, затем два варианта: первый метод унаследован, второй метод написан над. Здесь расширьте интерфейс: используйте их или метод реализации: логическая запись их. Полиморфизм, используемый для метода, наследование классов.

Второй ответ:

Есть ли разница между cm.start(); и rf.start();?

Да, оба являются объектами, которые совершенно разные по отношению друг к другу. Не создавайте объекты интерфейса, потому что Java не поддерживает интерфейсные объекты. Первый объект создан для интерфейса и второй для класса холодильников. Второй объект прямо сейчас.

Ответ 6

Самый общий ответ на общую часть вашего вопроса (почему я должен использовать полиморфизм?) заключается в том, что полиморфизм реализует несколько критических объектно-ориентированных принципов проектирования, например:

  • повторное использование кода: Поместив любой код, который является общим для всех ваших "охлаждающих машин" в охлаждающую машину, вам нужно только один раз написать этот код, и любые изменения в этом коде мгновенно истекают.

  • абстракция: Человеческий мозг может отслеживать только столько вещей, но они хороши в категориях и иерархиях. Это помогает понять, что происходит в большой программе.

  • Инкапсуляция: каждый класс скрывает детали того, что он делает, и просто основывается на интерфейсе базового класса.

  • разделение проблем: много объектно-ориентированного программирования связано с назначением обязанностей. Кто будет отвечать за это? Специализированные проблемы могут выполняться в подклассах.

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

Ответ 7

Простой вариант полиморфизма состоит в том, что у вас может быть массив охлаждения, где элемент 0 является холодильником, а элемент 1 - AirConditioner и т.д.

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

Это может быть большим преимуществом при приеме ввода от пользователя и необходимости перебора по всем объектам и вызова аналогичных функций

Ответ 8

Использование ваших объектов полиморфно также помогает создавать фабрики или семейства связанных классов, что является важной частью того, как Factory шаблон дизайна, Здесь очень простой пример полиморфного factory:

public CoolingMachine CreateCoolingMachines(string machineType)
{
    if(machineType == "ref")
        return new Refrigerator();
    //other else ifs to return other types of CoolingMachine family
}

использование вызова над кодом:

CoolingMachine cm = CreateCoolingMachine("AC"); //the cm variable will have a reference to Airconditioner class which is returned by CreateCoolingMachines() method polymorphically

Также представьте, что у вас есть метод, как показано ниже, который использует конкретный параметр класса Refrigerator:

public void UseObject(Refrigerator refObject)
{
    //Implementation to use Refrigerator object only
}

Теперь, если вы измените выше реализацию метода UseObject() для использования самого общего параметра базового класса, вызывающий код получит преимущество для передачи любого параметра, полиморфно, который затем может быть использован внутри метода UseObject():

public void UseObject(CoolingMachine coolingMachineObject)
{
    //Implementation to use Generic object and all derived objects
}

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

Ответ 9

Я приведу простой для понимания пример. Допустим, у вас есть json

{"a":[1,2],"sz":"text", "v":3, "f":1.2}

Теперь можно сказать, что программно вы хотите указать имя, тип и значение. Вместо того, чтобы иметь переключатель() для каждого типа (массив для a, строка для sz и т.д.), Вы можете просто иметь базовый тип и вызывать функцию, которая выполняет свою работу. Он также более эффективен с КПД, чем с помощью переключателя с дюжиной типов.

Тогда есть плагины, libs и внешний код с интерфейсом.