Полиморфизм против переопределения против перегрузки

в терминах Java, когда кто-то спрашивает:

Что такое полиморфизм?

б перегрузка или переопределение быть приемлемым ответом?

Я думаю, что есть немного больше, чем это.

если у вас был абстрактный базовый класс, который определил метод без реализации, и вы определили этот метод в подклассе, это все еще переопределение?

Я думаю, перегрузка это не правильный ответ наверняка.

22 ответов


ясный способ выразить полиморфизм через абстрактный базовый класс (или интерфейс)

public abstract class Human{
   ...
   public abstract void goPee();
}

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

так мы отложить реализацию с помощью абстрактных класс.

public class Male extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Stand Up");
    }
}

и

public class Female extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Sit Down");
    }
}

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

public static void main(String[] args){
    ArrayList<Human> group = new ArrayList<Human>();
    group.add(new Male());
    group.add(new Female());
    // ... add more...

    // tell the class to take a pee break
    for (Human person : group) person.goPee();
}

запуск этого даст:

Stand Up
Sit Down
...

полиморфизм - это способность экземпляр класса вести себя так, как если бы он был экземпляром другого класса в дереве наследования, чаще всего один из его классов-предков. Например, в Java все классы наследуются от Object. Поэтому можно создать переменную типа Object и назначить ей экземпляр любого класса.

An переопределить - Это тип функции, которая возникает в классе, который наследуется от другого класса. Функция переопределения " заменяет" функция, унаследованная от базового класса, но делает это таким образом, что она вызывается даже тогда, когда экземпляр ее класса притворяется другим типом через полиморфизм. Ссылаясь на предыдущий пример, вы можете определить свой собственный класс и переопределить метод toString() функция. Поскольку эта функция наследуется от Object, она будет доступна при копировании экземпляра этого класса в переменную типа Object. Обычно, если вы вызываете toString () в своем классе, пока он притворяется чтобы быть объектом, версия toString, которая фактически будет срабатывать, определяется на самом объекте. Однако, поскольку функция является переопределением, определение toString () из вашего класса используется, даже если истинный тип экземпляра класса скрыт за полиморфизмом.

перегрузка - это действие определения нескольких методов с одинаковым именем, но с разными параметрами. Он не связан ни с переопределением, ни с полиморфизмом.


вот пример полиморфизма в псевдо-C# / Java:

class Animal
{
    abstract string MakeNoise ();
}

class Cat : Animal {
    string MakeNoise () {
        return "Meow";
    }
}

class Dog : Animal {
    string MakeNoise () {
        return "Bark";
    }
}

Main () {
   Animal animal = Zoo.GetAnimal ();
   Console.WriteLine (animal.MakeNoise ());
}

основная функция не знает тип животного и зависит от поведения конкретной реализации метода MakeNoise ().

Edit:похоже, Брайан опередил меня. Забавно, что мы использовали один и тот же пример. Но вышеприведенный код должен помочь прояснить понятия.


полиморфизм означает более одной формы, один и тот же объект, выполняющий различные операции в соответствии с требованием.

полиморфизм может быть достигнут с помощью двух способов, это

  1. способ переопределения
  2. способ перегрузки

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

способ переопределение означает, что мы используем имена методов в разных классах,это означает, что метод родительского класса в дочернем классе.

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

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


для достижения полиморфизма используются как переопределение, так и перегрузка.

у вас может быть метод в классе это переопределяется в одном или еще подклассы. Метод делает разные вещи в зависимости от класс используется для создания объекта.

    abstract class Beverage {
       boolean isAcceptableTemperature();
    }

    class Coffee extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature > 70;
       }
    }

    class Wine extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature < 10;
       }
    }

У вас также может быть метод, который перегружен С двумя или более наборами аргументов. Метод делает различные вещи, основанные на тип(ы) аргумент(ы) принят.

    class Server {
        public void pour (Coffee liquid) {
            new Cup().fillToTopWith(liquid);
        }

        public void pour (Wine liquid) {
            new WineGlass().fillHalfwayWith(liquid);
        }

        public void pour (Lemonade liquid, boolean ice) {
            Glass glass = new Glass();
            if (ice) {
                glass.fillToTopWith(new Ice());
            }
            glass.fillToTopWith(liquid);
        }
    }

вы правы, что перегрузка не является ответом.

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


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

Я бы не согласился с некоторыми ответами здесь в том, что перегрузка является формой полиморфизма (параметрического полиморфизма) в случае, если метод с тем же именем может вести себя по-разному, давать разные типы параметров. Хорошим примером является перегрузка операторов. Вы можете определить "+", чтобы принять различные типы параметров - скажем, строки или int - и на основе этих типов " + " будут вести себя по-разному.

полиморфизм также включает методы наследования и переопределения, хотя они могут быть абстрактными или виртуальными в базовом типе. С точки зрения полиморфизма на основе наследования Java поддерживает только наследование одного класса, ограничивая его полиморфное поведение одной цепочкой базовых типов. Java поддерживает реализацию нескольких интерфейсов, которая является еще одной формой полиморфное поведение.


классический пример, собаки и кошки-животные, животные имеют метод makeNoise. Я могу перебирать массив животных, вызывающих makeNoise, и ожидать, что они сделают там соответствующую реализацию.

вызывающий код не должен знать, какое конкретно животное они.

вот что я думаю о полиморфизме.


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


ни:

перегрузка-это когда у вас одно и то же имя функции, которое принимает разные параметры.

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

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

в Java вы видите полиморфизм много с коллекциями:

int countStuff(List stuff) {
  return stuff.size();
}

List-базовый класс, компилятор не имеет понятия, считаете ли вы связанный список, вектор, массив или пользовательскую реализацию списка, если он действует как список:

List myStuff = new MyTotallyAwesomeList();
int result = countStuff(myStuff);

Если бы вы перегружались, у вас было бы:

int countStuff(LinkedList stuff) {...}
int countStuff(ArrayList stuff) {...}
int countStuff(MyTotallyAwesomeList stuff) {...}
etc...

и правильная версия countStuff() будет выбран компилятором для соответствия параметрам.


полиморфизм означает "много форм".

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

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

Итак, поскольку интерфейсы описывают поведение, а имена методов описывают поведение (для программиста), не слишком далеко рассматривать перегрузку метода как меньшую форму полиморфизма.


термин перегрузка относится к наличию нескольких версий чего-то с тем же именем, обычно методов с разными списками параметров

public int DoSomething(int objectId) { ... }
public int DoSomething(string objectName) { ... }

таким образом, эти функции могут делать то же самое, но у вас есть возможность вызвать его с идентификатором или именем. Не имеет ничего общего с наследованием, абстрактными классами и т. д.

переопределение обычно относится к полиморфизму, как вы описали в своем вопросе


переопределение больше похоже на скрытие унаследованного метода путем объявления метода с тем же именем и сигнатурой, что и метод верхнего уровня (super method), это добавляет полиморфное поведение к классу . другими словами, решение о выборе метода уровня, который будет вызван, будет принято во время выполнения, а не во время компиляции . это приводит к концепции интерфейса и реализации .


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

  class Vehicle{  
      void run()
          {
           System.out.println("Vehicle is running");
          }  
               }
   class Bike2 extends Vehicle{  
       void run()
           {
            System.out.println("Bike is running safely");
           }  

    public static void main(String args[]){  
    Bike2 obj = new Bike2();  
    obj.run();  
     }  

выход: велосипед бежит безопасно........ Чтобы понять переопределение более четко, посетите:http://javabyroopam.blogspot.in/

перегрузка Просто два метода, которые имеют одно и то же имя, но имеют другой список аргументов называется перегрузкой..

   class Calculation{  
      void sum(int a,int b){System.out.println(a+b);}  
      void sum(int a,int b,int c){System.out.println(a+b+c);}  

      public static void main(String args[]){  
      Calculation obj=new Calculation();  
      obj.sum(10,10,10);  
       obj.sum(20,20);  

       }  
    }  

выход 30,20


что такое полиморфизм?

из java учебник

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

рассматривая примеры и определения, переопределение должен быть принят ответ.

относительно вашего второго запроса:

если у вас был абстрактный базовый класс, который определил метод без реализации, и вы определили этот метод в подклассе, это все еще переопределение?

это должно называться переопределением.

взгляните на это пример для понимания различных типов переопределения.

  1. базовый класс не предоставляет реализации, и подкласс должен переопределить метод complete - (abstract)
  2. базовый класс обеспечивает реализацию по умолчанию, а подкласс может изменить поведение
  3. подкласс добавляет расширение к реализации базового класса, вызывая super.methodName() как первое заявление
  4. базовый класс определяет структуру алгоритма (метод шаблона), а подкласс будет переопределить часть алгоритма

фрагмент кода:

import java.util.HashMap;

abstract class Game implements Runnable{

    protected boolean runGame = true;
    protected Player player1 = null;
    protected Player player2 = null;
    protected Player currentPlayer = null;

    public Game(){
        player1 = new Player("Player 1");
        player2 = new Player("Player 2");
        currentPlayer = player1;
        initializeGame();
    }

    /* Type 1: Let subclass define own implementation. Base class defines abstract method to force
        sub-classes to define implementation    
    */

    protected abstract void initializeGame();

    /* Type 2: Sub-class can change the behaviour. If not, base class behaviour is applicable */
    protected void logTimeBetweenMoves(Player player){
        System.out.println("Base class: Move Duration: player.PlayerActTime - player.MoveShownTime");
    }

    /* Type 3: Base class provides implementation. Sub-class can enhance base class implementation by calling
        super.methodName() in first line of the child class method and specific implementation later */
    protected void logGameStatistics(){
        System.out.println("Base class: logGameStatistics:");
    }
    /* Type 4: Template method: Structure of base class can't be changed but sub-class can some part of behaviour */
    protected void runGame() throws Exception{
        System.out.println("Base class: Defining the flow for Game:");  
        while ( runGame) {
            /*
            1. Set current player
            2. Get Player Move
            */
            validatePlayerMove(currentPlayer);  
            logTimeBetweenMoves(currentPlayer);
            Thread.sleep(500);
            setNextPlayer();
        }
        logGameStatistics();
    }
    /* sub-part of the template method, which define child class behaviour */
    protected abstract void validatePlayerMove(Player p);

    protected void setRunGame(boolean status){
        this.runGame = status;
    }
    public void setCurrentPlayer(Player p){
        this.currentPlayer = p;
    }
    public void setNextPlayer(){
        if ( currentPlayer == player1) {
            currentPlayer = player2;
        }else{
            currentPlayer = player1;
        }
    }
    public void run(){
        try{
            runGame();
        }catch(Exception err){
            err.printStackTrace();
        }
    }
}

class Player{
    String name;
    Player(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
}

/* Concrete Game implementation  */
class Chess extends Game{
    public Chess(){
        super();
    }
    public void initializeGame(){
        System.out.println("Child class: Initialized Chess game");
    }
    protected void validatePlayerMove(Player p){
        System.out.println("Child class: Validate Chess move:"+p.getName());
    }
    protected void logGameStatistics(){
        super.logGameStatistics();
        System.out.println("Child class: Add Chess specific logGameStatistics:");
    }
}
class TicTacToe extends Game{
    public TicTacToe(){
        super();
    }
    public void initializeGame(){
        System.out.println("Child class: Initialized TicTacToe game");
    }
    protected void validatePlayerMove(Player p){
        System.out.println("Child class: Validate TicTacToe move:"+p.getName());
    }
}

public class Polymorphism{
    public static void main(String args[]){
        try{

            Game game = new Chess();
            Thread t1 = new Thread(game);
            t1.start();
            Thread.sleep(1000);
            game.setRunGame(false);
            Thread.sleep(1000);

            game = new TicTacToe();
            Thread t2 = new Thread(game);
            t2.start();
            Thread.sleep(1000);
            game.setRunGame(false);

        }catch(Exception err){
            err.printStackTrace();
        }       
    }
}

выход:

Child class: Initialized Chess game
Base class: Defining the flow for Game:
Child class: Validate Chess move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate Chess move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
Child class: Add Chess specific logGameStatistics:
Child class: Initialized TicTacToe game
Base class: Defining the flow for Game:
Child class: Validate TicTacToe move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate TicTacToe move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:

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

Почему полиморфизм так важен в любом языке ООП.

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

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

вы начинаете с написания классов для каждой из этих функций, добавив

  1. set: - установить значение контроллера.(Предположим, что это имеет код контроллера)
  2. get: - чтобы получить значение контроллера.(Предположим, что это имеет код контроллера)
  3. adjust: - для проверки ввода и настройки контроллера.(Общий корректность.. независимо от контроллеров)
  4. отображение пользовательского ввода с контроллерами : - для получения пользовательского ввода и вызова контроллеров соответственно.

Версия Приложения 1

import java.util.Scanner;    
class VolumeControllerV1 {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class  BrightnessControllerV1 {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class ColourControllerV1    {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

/*
 *       There can be n number of controllers
 * */
public class TvApplicationV1 {
    public static void main(String[] args)  {
        VolumeControllerV1 volumeControllerV1 = new VolumeControllerV1();
        BrightnessControllerV1 brightnessControllerV1 = new BrightnessControllerV1();
        ColourControllerV1 colourControllerV1 = new ColourControllerV1();


        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println("Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV1.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV1.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV1.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV1.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV1.adjust(5);
                    break;
                }
                case 6: {
                colourControllerV1.adjust(-5);
                break;
            }
            default:
                System.out.println("Shutting down...........");
                break OUTER;
        }

    }
    }
}

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

проблемы в ТВ-приложении версии 1

  1. отрегулируйте (int значение) код повторяющиеся во всех трех классах. Вы хотели бы свести к минимуму дублирование кода. (Но вы не подумали об общем коде и переместили его в какой-то супер класс, чтобы избежать дублирования кода)

вы решили жить с этим, пока ваше приложение работает так, как ожидалось.

после Иногда, ваш босс возвращается к вам и просит вас добавить функцию сброса в существующее приложение. Reset установит все 3 трех контроллера по умолчанию ценности.

вы начинаете писать новый класс (ResetFunctionV2) для новой функциональности и сопоставляете код отображения пользовательского ввода для этой новой функции.

Версия Приложения 2

import java.util.Scanner;
class VolumeControllerV2    {

    private int defaultValue = 25;
    private int value;

    int getDefaultValue() {
        return defaultValue;
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class  BrightnessControllerV2   {

    private int defaultValue = 50;
    private int value;
    int get()    {
        return value;
    }
    int getDefaultValue() {
        return defaultValue;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class ColourControllerV2    {

    private int defaultValue = 40;
    private int value;
    int get()    {
        return value;
    }
    int getDefaultValue() {
        return defaultValue;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

class ResetFunctionV2 {

    private VolumeControllerV2 volumeControllerV2 ;
    private BrightnessControllerV2 brightnessControllerV2;
    private ColourControllerV2 colourControllerV2;

    ResetFunctionV2(VolumeControllerV2 volumeControllerV2, BrightnessControllerV2 brightnessControllerV2, ColourControllerV2 colourControllerV2)  {
        this.volumeControllerV2 = volumeControllerV2;
        this.brightnessControllerV2 = brightnessControllerV2;
        this.colourControllerV2 = colourControllerV2;
    }
    void onReset()    {
        volumeControllerV2.set(volumeControllerV2.getDefaultValue());
        brightnessControllerV2.set(brightnessControllerV2.getDefaultValue());
        colourControllerV2.set(colourControllerV2.getDefaultValue());
    }
}
/*
 *       so on
 *       There can be n number of controllers
 *
 * */
public class TvApplicationV2 {
    public static void main(String[] args)  {
        VolumeControllerV2 volumeControllerV2 = new VolumeControllerV2();
        BrightnessControllerV2 brightnessControllerV2 = new BrightnessControllerV2();
        ColourControllerV2 colourControllerV2 = new ColourControllerV2();

        ResetFunctionV2 resetFunctionV2 = new ResetFunctionV2(volumeControllerV2, brightnessControllerV2, colourControllerV2);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV2.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV2.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV2.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV2.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV2.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV2.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV2.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

таким образом, у вас есть приложение готово с функцией сброса. Но, теперь вы начинаете понимать, что

проблемы в ТВ-приложении версии 2

  1. если новый регулятор введен к продукту, то вы необходимо изменить код функции сброса.
  2. если количество контроллеров растет очень высоко, у вас будет проблема с удержанием ссылок контроллеров.
  3. сброс кода функции тесно связан с кодом всех контроллеров класса (для получения и установки значений по умолчанию).
  4. Reset feature class (ResetFunctionV2) может получить доступ к другому методу класса контроллера (adjust), который нежелателен.

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

теперь вы начинаете думать, что эта новая функция, которая будет добавлена напоминает с функцией сброса и вопросы применения (V2) будет умножаться, если вы не повторно фактор вашего приложения.

вы начинаете думать об использовании наследования, чтобы вы могли воспользоваться полиморфная способность JAVA, и вы добавляете новый абстрактный класс (ControllerV3) в

  1. объявить подпись метода get и set.
  2. содержит реализацию метода adjust, которая ранее была реплицирована среди всех контроллеров.
  3. объявите метод setDefault, чтобы функция сброса могла быть легко реализована с использованием полиморфизма.

С этими улучшениями, у вас есть версия 3 вашего приложения TV готов с вы.

Версия Приложения 3

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

abstract class ControllerV3 {
    abstract void set(int value);
    abstract int get();
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
    abstract void setDefault();
}
class VolumeControllerV3 extends ControllerV3   {

    private int defaultValue = 25;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
}
class  BrightnessControllerV3  extends ControllerV3   {

    private int defaultValue = 50;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
}
class ColourControllerV3 extends ControllerV3   {

    private int defaultValue = 40;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
}

class ResetFunctionV3 {

    private List<ControllerV3> controllers = null;

    ResetFunctionV3(List<ControllerV3> controllers)  {
        this.controllers = controllers;
    }
    void onReset()    {
        for (ControllerV3 controllerV3 :this.controllers)  {
            controllerV3.setDefault();
        }
    }
}
/*
 *       so on
 *       There can be n number of controllers
 *
 * */
public class TvApplicationV3 {
    public static void main(String[] args)  {
        VolumeControllerV3 volumeControllerV3 = new VolumeControllerV3();
        BrightnessControllerV3 brightnessControllerV3 = new BrightnessControllerV3();
        ColourControllerV3 colourControllerV3 = new ColourControllerV3();

        List<ControllerV3> controllerV3s = new ArrayList<>();
        controllerV3s.add(volumeControllerV3);
        controllerV3s.add(brightnessControllerV3);
        controllerV3s.add(colourControllerV3);

        ResetFunctionV3 resetFunctionV3 = new ResetFunctionV3(controllerV3s);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV3.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV3.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV3.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV3.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV3.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV3.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV3.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

хотя большинство проблем, перечисленных в списке проблем V2, были рассмотрены, кроме

проблемы в ТВ-приложении версии 3

  1. Reset feature class (ResetFunctionV3) может получить доступ к другому методу класса контроллера (adjust), который нежелателен.

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

таким образом, Вы разделяете контракт, определенный в абстрактном классе, и пишете 2 интерфейса для

  1. сброс.
  2. Обновить Драйвер.

и ваш 1-й конкретный класс реализует их, как показано ниже

Версия Приложения 4

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

interface OnReset {
    void setDefault();
}
interface OnStart {
    void checkForDriverUpdate();
}
abstract class ControllerV4 implements OnReset,OnStart {
    abstract void set(int value);
    abstract int get();
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

class VolumeControllerV4 extends ControllerV4 {

    private int defaultValue = 25;
    private int value;
    @Override
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for VolumeController .... Done");
    }
}
class  BrightnessControllerV4 extends ControllerV4 {

    private int defaultValue = 50;
    private int value;
    @Override
    int get()    {
        return value;
    }
    @Override
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }

    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for BrightnessController .... Done");
    }
}
class ColourControllerV4 extends ControllerV4 {

    private int defaultValue = 40;
    private int value;
    @Override
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for ColourController .... Done");
    }
}
class ResetFunctionV4 {

    private List<OnReset> controllers = null;

    ResetFunctionV4(List<OnReset> controllers)  {
        this.controllers = controllers;
    }
    void onReset()    {
        for (OnReset onreset :this.controllers)  {
            onreset.setDefault();
        }
    }
}
class InitializeDeviceV4 {

    private List<OnStart> controllers = null;

    InitializeDeviceV4(List<OnStart> controllers)  {
        this.controllers = controllers;
    }
    void initialize()    {
        for (OnStart onStart :this.controllers)  {
            onStart.checkForDriverUpdate();
        }
    }
}
/*
*       so on
*       There can be n number of controllers
*
* */
public class TvApplicationV4 {
    public static void main(String[] args)  {
        VolumeControllerV4 volumeControllerV4 = new VolumeControllerV4();
        BrightnessControllerV4 brightnessControllerV4 = new BrightnessControllerV4();
        ColourControllerV4 colourControllerV4 = new ColourControllerV4();
        List<ControllerV4> controllerV4s = new ArrayList<>();
        controllerV4s.add(brightnessControllerV4);
        controllerV4s.add(volumeControllerV4);
        controllerV4s.add(colourControllerV4);

        List<OnStart> controllersToInitialize = new ArrayList<>();
        controllersToInitialize.addAll(controllerV4s);
        InitializeDeviceV4 initializeDeviceV4 = new InitializeDeviceV4(controllersToInitialize);
        initializeDeviceV4.initialize();

        List<OnReset> controllersToReset = new ArrayList<>();
        controllersToReset.addAll(controllerV4s);
        ResetFunctionV4 resetFunctionV4 = new ResetFunctionV4(controllersToReset);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV4.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV4.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV4.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV4.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV4.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV4.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV4.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

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

  1. держите различную часть применения свободно Соединенным.(Компоненты функции сброса или обновления драйверов не должны быть осведомлены о фактических классах контроллера (громкость, яркость и цвет), любой класс, реализующий OnReset или OnStart, будет приемлемым для сброса или обновления драйверов компонентов функции соответственно).
  2. улучшение приложений становится проще.(Новый добавление контроллера не повлияет на сброс или обновление драйвера, и теперь вам очень легко добавить новые)
  3. сохранить слой абстракции.(Теперь функция сброса может видеть только метод setDefault контроллеров и функция сброса может видеть только метод checkfordriverupdate контроллеров)

надеюсь, это помогает :-)


перегрузка - это когда вы определяете 2 метода с одинаковым именем, но разными параметрами

переопределение, в котором можно изменить поведение базового класса с помощью функции с тем же именем в подклассе.

таким образом, полиморфизм связан с переопределением,но не с перегрузкой.

однако, если кто-то дал мне простой ответ "переопределения" на вопрос "Что такое полиморфизм?- Я бы попросил дальнейших объяснений.


полиморфизм более вероятен, поскольку это смысл это ... для переопределения в java

это все о различном поведении одного и того же объекта в разных ситуациях(в способе программирования ... вы можете называть разные аргументы)

Я думаю, что приведенный ниже пример поможет вам понять ... Хотя это не чистый java-код ...

     public void See(Friend)
     {
        System.out.println("Talk");
     }

но если мы изменим аргумент ... поведение будет изменено ...

     public void See(Enemy)
     {
        System.out.println("Run");
     }

человек (здесь "объект") такой же ...


полиморфизм-это несколько реализаций объекта или, можно сказать, несколько форм объекта. допустим у вас есть класс Animals как абстрактный базовый класс, и он имеет метод, называемый movement() который определяет способ перемещения животного. На самом деле у нас есть разные виды животных, и они двигаются по-разному, некоторые из них с двумя ногами, другие с четырьмя, а некоторые без ног и т. д.. Чтобы определить разные movement() каждого животного на Земле нам нужно применить полиморфизм. Однако вам нужно определить больше классов, т. е. class Dogs Cats Fish etc. Затем вам нужно расширить эти классы из базового класса Animals и переопределить его метод movement() С новой функциональностью движения на основе каждого животного у вас есть. Вы также можете использовать Interfaces для достижения этой цели. Ключевое слово здесь переопределяет, перегрузка отличается и не рассматривается как полиморфизм. с перегрузкой вы можете определить несколько методов "с тем же именем", но с разными параметрами на одном и том же объект или класс.


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

  1. Позднее Связывание
  2. наследование.

сказав, что перегрузка означает что-то другое для переопределение в зависимости от используемого языка. Например, в Java не существует переопределение но перегрузка. перегружен методы с разными сигнатурами для своего базового класса доступны в подклассе. Иначе они были бы переопределяется (пожалуйста, посмотрите, что я имею в виду теперь факт, что нет способа вызвать метод базового класса извне объекта).

но в C++ это не так. Любой перегружен способ, самостоятельно ли подписи или нет (diffrrent сумму, другой тип) также переопределяется. То есть на сегодняшний день метод базового класса больше не доступен в подклассе при вызове извне объекта подкласса, очевидно.

таким образом, ответ заключается в том, когда речь идет об использовании Java перегрузка. На любом другом языке может быть иначе, как это происходит в c++


полиморфизм относится к способности языка иметь различный объект, обработанный равномерно с помощью одного интерфейса; как таковой он связан с переопределением, поэтому интерфейс (или базовый класс) является полиморфным, реализующим является объект, который переопределяет (две грани одной медали)

во всяком случае, разница между двумя терминами лучше объясняется с помощью других языков, таких как c++: полиморфный объект в c++ ведет себя как аналог java, если базовая функция является виртуальным, но если метод не является виртуальным, переход кода разрешен статически, а истинный тип не проверяется во время выполнения, поэтому полиморфизм включает способность объекта вести себя по-разному в зависимости от интерфейса, используемого для доступа к нему; позвольте мне привести пример в псевдокоде:

class animal {
    public void makeRumor(){
        print("thump");
    }
}
class dog extends animal {
    public void makeRumor(){
        print("woff");
    }
}

animal a = new dog();
dog b = new dog();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

(предположим, что makeRumor не является виртуальным)

java действительно не предлагает этот уровень полиморфизма (называемый также разрезанием объектов).

животное a = новый собака(); собака b = новая собака ();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

в обоих случаях он будет печатать только вуф.. поскольку a и b относятся к классу dog


import java.io.IOException;

class Super {

    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName() + " - I'm parent");
        return null;
    }

}

class SubOne extends Super {

    @Override
    protected Super getClassName(Super s)  {
        System.out.println(this.getClass().getSimpleName() + " - I'm Perfect Overriding");
        return null;
    }

}

class SubTwo extends Super {

    @Override
    protected Super getClassName(Super s) throws NullPointerException {
        System.out.println(this.getClass().getSimpleName() + " - I'm Overriding and Throwing Runtime Exception");
        return null;
    }

}

class SubThree extends Super {

    @Override
    protected SubThree getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Returning SubClass Type");
        return null;
    }

}

class SubFour extends Super {

    @Override
    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Throwing Narrower Exception ");
        return null;
    }

}

class SubFive extends Super {

    @Override
    public Super getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and have broader Access ");
        return null;
    }

}

class SubSix extends Super {

    public Super getClassName(Super s, String ol) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading ");
        return null;
    }

}

class SubSeven extends Super {

    public Super getClassName(SubSeven s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading because Method signature (Argument) changed.");
        return null;
    }

}

public class Test{

    public static void main(String[] args) throws Exception {

        System.out.println("Overriding\n");

        Super s1 = new SubOne(); s1.getClassName(null);

        Super s2 = new SubTwo(); s2.getClassName(null);

        Super s3 = new SubThree(); s3.getClassName(null);

        Super s4 = new SubFour(); s4.getClassName(null);

        Super s5 = new SubFive(); s5.getClassName(null);

        System.out.println("Overloading\n");

        SubSix s6 = new SubSix(); s6.getClassName(null, null);

        s6 = new SubSix(); s6.getClassName(null);

        SubSeven s7 = new SubSeven(); s7.getClassName(s7);

        s7 = new SubSeven(); s7.getClassName(new Super());

    }
}