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

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

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

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

Я думаю, здесь есть кое-что еще.

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

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


person Brian G    schedule 30.09.2008    source источник
comment
Ниже ответы очень хорошо объясняют полиморфизм. Но я категорически возражаю против того, чтобы сказать, что перегрузка - это тип полиморфизма, который я пытался оправдать в своем вопросе и ответе, который на самом деле сосредоточен на перегрузке, является полиморфизмом или нет. Я попытался оправдать ответ @The Digital Gabeg, присутствующий в этой ветке. Обратитесь к Уточнение: перегрузка метода статическая / привязка времени компиляции, но не полиморфизм. Правильно ли соотносить статическое связывание с полиморфизмом?   -  person PraveenKumar Lalasangi    schedule 04.10.2019


Ответы (20)


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

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

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

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

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
...
person Chris Cudmore    schedule 30.09.2008
comment
@yuudachi. Я придумал этот пример, когда преподавал в классе. Канонический класс Bank Account на самом деле не выражал абстрактности базового класса. Другой канонический пример (Животное, шуметь) был слишком абстрактным для понимания. Я искал единую базу со слишком очевидными подклассами. На самом деле goPee () был единственным примером, который не был сексистским или стереотипным. (хотя в классе я распечатал по коридору слева вместо того, чтобы вставать или садиться.) - person Chris Cudmore; 20.11.2010
comment
Этот пример также хорошо подчеркивает сложность использования иерархической системы для описания биологических систем. Некоторые люди, например очень молодые, мочатся практически в любом положении, а младенцам нелегко сказать идти Пи (). Некоторые люди являются интерсексуалами, и их биологические ярлыки мужского или женского пола становятся довольно нечеткими; социальные значения еще более сложны. В качестве обучающего примера он показывает, как предположения моделирования могут иметь отрицательные результаты, например, предполагать, что кто-то (например, студент объектно-ориентированного программирования), страдающий недержанием мочи или интерсексом, на самом деле не человек. - person Andrew Dalke; 01.02.2013
comment
Я могу вспомнить по крайней мере горстку людей, которые опровергли бы ваш тезис о том, что вы не можете создать человека, который не является ни мужским, ни женским тезисом, хотя это все равно будет верно в отношении вашего кода ... плохая абстракция, я полагаю, я говорю? ;) - person Frank W. Zammetti; 01.02.2013
comment
Я думаю, важно отметить, что это всего лишь полиморфизм, потому что какая версия goPee () для вызова может быть определена только во время выполнения. Хотя этот пример подразумевает это, приятно указать, почему именно это полиморфизм. Кроме того, для этого не требуются родственные классы. Это также могут быть отношения между родителями и детьми. Или даже совершенно не связанные классы, которые по совпадению выполняют одну и ту же функцию. Примером этого может быть функция .toString (). Это может быть вызвано случайным образом для любого объекта, но компилятор никогда не может точно знать, какой тип объекта. - person Tor Valamo; 02.02.2013
comment
... если не указано иное, очевидно. - person Tor Valamo; 02.02.2013
comment
@AndrewDalke, +1 за заметки о биологической сложности. Кроме того, goPee не принимает на вход гравитационное поле. Эта зависимость от глобального состояния затрудняет модульное тестирование CatheterizedIntersexAstronaut и показывает, что создание подклассов не всегда может быть лучшим методом для композиции признаков. - person Mike Samuel; 02.02.2013
comment
@Tor Valamo - необходимость разрешения полиморфизма во время выполнения, похоже, в некоторой степени зависит от контекста и определения того, чьи определения вы используете. Например, раннее связывание (перегрузка) также иногда называют полиморфизмом времени компиляции, а шаблоны в C ++ можно рассматривать как еще один механизм полиморфизма времени компиляции. - person Steve314; 03.02.2013
comment
@AndrewDalke, что, если бы принцип ООП был объяснен с помощью классов Cat и Dog, которые являются подклассами абстрактного класса Animal? Значит ли это, что мышь из-за этого не животное? - person humkins; 22.09.2016
comment
Затем идет GDPR, в котором говорится, что компании не должны помнить, что человеческие мочы стоят или опускаются. - person Shanu Gupta; 31.05.2018
comment
есть ли другой пример полиморфизма времени выполнения в Java, кроме переопределения? - person Amrit; 29.04.2020
comment
Это буквально лучший пример, который можно было бы попросить - person Vignesh Kesavan; 14.07.2020
comment
Можете ли вы упомянуть, зачем добавлять аннотации с помощью @override? мы не отменяем право? мы реализуем определение. - person Ali; 27.12.2020
comment
@Ali Аннотацию переопределения можно использовать не только для переопределения, но и для реализации в Java, и это желательно. Причина в том, что если метод в суперклассе или интерфейсе (независимо от того, является ли он конкретной реализацией, абстрактным классом или частью определения интерфейса) изменил свою сигнатуру или был удален, компилятор покажет ошибку для аннотированных методов. И наоборот, если вы поместите аннотацию к методу, но допустили небольшую ошибку в его сигнатуре (опечатка, аргументы, исключения), компилятор это заметит. Это предотвращает ошибки во время компиляции. - person G_H; 12.05.2021
comment
@G_H Это было очень полезно! Спасибо! - person Ali; 12.05.2021

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

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

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

person The Digital Gabeg    schedule 30.09.2008
comment
Это старый, но полиморфизм не означает, что другой класс должен быть в дереве наследования. Это верно в Java, если вы считаете интерфейсы частью дерева наследования, но не в Go, где интерфейсы реализованы неявно. - person J.N.; 01.03.2011
comment
Собственно, классы для полиморфизма вообще не нужны. - person StCredZero; 02.02.2013
comment
Я новичок, поправьте меня, если я ошибаюсь, но я бы не сказал, что перегрузка не связана с полиморфизмом. По крайней мере, в Java полиморфизм - это когда реализация выбирается на основе типа вызывающего, а перегрузка - это когда реализация выбирается на основе типа параметров, не так ли? Сходство между ними помогает мне понять это. - person csjacobs24; 26.03.2015
comment
Неправильно. Ad hoc polymorphism - это то, что вы описали в разделе Перегрузка, а - это случай полиморфизма. - person Jossie Calderon; 23.06.2016
comment
Это не связано ни с переопределением, ни с полиморфизмом. Это утверждение неверно. - person Shailesh Pratapwar; 16.05.2018
comment
Как я понимаю, статический полиморфизм это же перегрузка. можете уточнить плз. - person Mohammad Ghanem; 11.11.2018
comment
Я думаю, что перегрузка - это случай полиморфизма. - person Minh Nghĩa; 12.04.2019
comment
Специальный полиморфизм - это точка зрения авторов, которая вошла даже в Википедию. Но java doc остается в стороне от этого и упоминает только о полиморфизме, и если вы откроете раздел javadoc для перегрузки метода, нигде не упоминается, что это специальный полиморфизм. Это здравый смысл для людей, которые глубоко понимают полиморфизм, и понимание полиморфизма заставляет их не соотносить эту специальную концепцию с полиморфизмом. - person PraveenKumar Lalasangi; 14.10.2019

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

Полиморфизма можно достичь двумя способами:

  1. Переопределение метода
  2. Перегрузка метода

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

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

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

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

person manoj    schedule 21.10.2012
comment
+1 за хороший ответ. Принятый ответ объясняет только один тип полиморфизма. Это полный ответ. - person apadana; 15.07.2015
comment
полиморфизм - это парадигма (ООП), но переопределение и перегрузка - это языковые средства. - person 曾其威; 28.07.2017
comment
Полиморфизм также может быть достигнут с помощью универсального типа. - person Minh Nghĩa; 12.04.2019

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

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

    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);
        }
    }
person Patrick McElhaney    schedule 30.09.2008
comment
Я полагаю, это было отклонено, потому что исторически перегрузка метода не рассматривается как часть полиморфизма в объектно-ориентированной парадигме. Перегрузка методов и полиморфизм - две ортогональные независимые особенности языка программирования. - person Sergio Acosta; 01.10.2008
comment
Как я сказал в своем ответе здесь, я не согласен - эти две функции не ортогональны, но тесно связаны. Полиморфизм! = Наследование. Мой голос за вас. - person Peter Meyer; 01.10.2008
comment
Другими словами, полиморфизм типов против специального полиморфизма. Я поддерживаю этот ответ, даже если он не такой полный, как должен, потому что в нем правильно указано, что и перегрузка, и переопределение связаны с полиморфизмом. Сказать, что полиморфизм в языках ООП может быть достигнут только путем наследования классов, просто неверно - мы должны помнить, что есть некоторые другие языки ООП, помимо Java и C ++, где можно использовать такие концепции, как множественная диспетчеризация, специальный полиморфизм, параметрический полиморфизм и т. Д. . - person rsenna; 18.09.2014
comment
@rsenna Это может быть неполно, но он отвечает на вопрос намного лучше, чем остальные ИМХО. Также очень приятно, что вы упомянули специальный и параметрический полиморфизм. - person Valentin Radu; 20.06.2015

Вот пример полиморфизма в псевдо-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 ());
}

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

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

person Mark A. Nicolosi    schedule 30.09.2008
comment
Это пример полиморфизма времени выполнения. Полиморфизм времени компиляции также возможен за счет перегрузки методов и универсальных типов. - person Pete Kirkham; 04.07.2010
comment
Форма - ›Параллелограмм -› Прямоугольник - ›Квадрат - person mpen; 11.09.2010
comment
@ yankee2905 в этом случае, я думаю, вы могли бы использовать интерфейсы, поскольку класс может реализовывать несколько интерфейсов. - person Sam003; 05.07.2015
comment
@Zhisheng Или добавление метода pee в абстрактный родительский класс? Я бы использовал интерфейс для реализации чего-то еще. - person joey rohan; 08.08.2015

Вы правы, что перегрузка - это не ответ.

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

person Alex B    schedule 30.09.2008
comment
Изменяется не поведение объекта, а его реализация. То же поведение, другая реализация, это полиморфизм. - person QBziZ; 01.10.2008
comment
@QBziZ Вам необходимо определить поведение, особенно прилагательное то же. Если поведение такое же, почему их реализация должна отличаться? Дело не в том, что кто-то недоволен определенной реализацией, следовательно, требуется другая. - person Sнаđошƒаӽ; 19.07.2016

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

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

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

person Peter Meyer    schedule 30.09.2008
comment
Вы правы в том, что означают эти слова в целом, но в контексте программирования, когда люди говорят «полиморфизм», они всегда имеют в виду полиморфизм, основанный на наследовании. Интересный момент, но я думаю, что такое описание полиморфизма запутает людей. - person The Digital Gabeg; 01.10.2008
comment
Может быть, проще объяснить полиморфизм только с точки зрения наследования, но то, как был задан этот конкретный вопрос, я думаю, что разумно также описать параметрический полиморфизм. - person Patrick McElhaney; 01.10.2008
comment
Чтобы быть ясным, я думаю, что следует указать различные формы - что я даже не сделал должным образом - потому что здесь есть несколько ответов, которые представлены как абсолютные. Я с уважением не согласен с тем, что в контексте программиста ... «полиморфизм» всегда означает «полиморфизм на основе наследования». - person Peter Meyer; 01.10.2008
comment
я думаю, что перегрузку лучше классифицировать как Ad-hoc_polymorphism en.wikipedia - person Manu; 08.12.2010
comment
Я склонен согласиться с «Цифровым Гейбегом» в том, что касается следования. Если вы обсуждаете ООП, полиморфизм обычно означает полиморфизм подтипа, а если вы обсуждаете теорию типов, он означает любой тип полиморфизма. Но, как вы говорите, с «контекстом программиста» это слишком двусмысленно, чтобы высмеивать. - person Manu; 08.12.2010
comment
+1 для полиморфизма - это просто способность объекта специализировать свое поведение в зависимости от его типа; что подкласс может переопределить метод, который обеспечивает более конкретное поведение для подкласса, и что среда выполнения знает, какой метод вызывать, в зависимости от типа объекта, который у него есть. - person 8bitjunkie; 06.04.2014

Полиморфизм просто означает «Множество форм».

Он НЕ ТРЕБУЕТ наследования для достижения ... поскольку реализация интерфейса, которая вообще не является наследованием, обслуживает полиморфные потребности. Возможно, реализация интерфейса удовлетворяет полиморфным потребностям «лучше», чем наследование.

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

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

person BillC    schedule 20.12.2010
comment
Определенно лучший ответ. Полиморфизм может применяться ко всем языковым конструкциям, будь то существительные (классы) или глаголы (методы). - person Radu Gasler; 26.05.2012

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

Код вызова не обязательно должен знать, что это за животное.

Это то, что я считаю полиморфизмом.

person Brian G    schedule 30.09.2008

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

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

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

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

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

  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 value) повторяется во всех трех классах. Вы хотели бы минимизировать дублирование кода. (Но вы не придумали общий код и не перенесли его в какой-то суперкласс, чтобы избежать дублирования кода)

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

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

Вы начинаете писать новый класс (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 (ResetFunctionV2) может обращаться к другому методу класса Controller (adjust), что нежелательно.

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

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

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

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

Благодаря этим улучшениям у вас есть готовая версия 3 вашего ТВ-приложения.

Версия приложения 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 (ResetFunctionV3) может обращаться к другому методу класса Controller (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)

Надеюсь это поможет :-)

person Developer    schedule 06.05.2018

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

person mxg    schedule 30.09.2008

Ни один:

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

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

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

В Java вы часто видите полиморфизм с библиотекой коллекций:

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

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

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

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

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

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

person Jason Peacock    schedule 30.09.2008

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

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

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

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

person Matt    schedule 30.09.2008

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

Из руководства по java

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

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

Что касается вашего второго запроса:

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

Это следует назвать перекрывающим.

Взгляните на этот пример, чтобы понять различные типы переопределения.

  1. Базовый класс не обеспечивает реализации, а подкласс должен переопределить полный метод - (аннотация)
  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:
person Ravindra babu    schedule 16.09.2016

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

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

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

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

person Clyde    schedule 30.09.2008

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

person Genjuro    schedule 26.04.2013

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

person SolidSnake    schedule 15.09.2013

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

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

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

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

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

person user1154840    schedule 24.02.2012

Полиморфизм более вероятен в том, что касается его значения ... для ПЕРЕХОДА в java

Все дело в разном поведении одного и того же объекта в разных ситуациях (в программировании ... вы можете вызывать разные АРГУМЕНТЫ)

Я думаю, что приведенный ниже пример поможет вам понять ... Хотя это не ЧИСТЫЙ java-код ...

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

Но если мы изменим АРГУМЕНТ ... ПОВЕДЕНИЕ изменится ...

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

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

person Rajan    schedule 11.09.2012

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

в любом случае разницу между этими двумя терминами лучше объяснить с использованием других языков, таких как 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

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

person Lorenzo Boccaccia    schedule 30.09.2008
comment
животное a = новая собака (); a был построен как собака, и будет печатать woff. Если вы хотите, чтобы он напечатал удар, вам нужно его улучшить. ((Животное) a) .makeRumor () - person Chris Cudmore; 01.10.2008
comment
Это отсылка к апкастингу, но объект по-прежнему остается собакой. Если вы хотите, чтобы это было животное, вы должны явно улучшить объект. - person Chris Cudmore; 01.10.2008
comment
Догадаться. Вопрос был помечен как Java. Вы ответили на C ++. Возможно, вы правы в C ++. Я определенно прав в Java. - person Chris Cudmore; 01.10.2008
comment
должно происходить каждый раз, когда задействован конструктор копирования, вот ссылка fredosaurus.com / notes-cpp / oop-condestructors / случай три совпадения; игнорируйте новый оператор, который нужен только для устранения неоднозначности создания. - person Lorenzo Boccaccia; 01.10.2008
comment
нашел исчерпывающее (и лучшее) объяснение для дальнейшего чтения: bytes.com/forum/post2982201-3 .html - person Lorenzo Boccaccia; 01.10.2008
comment
извините за пламя, я делал этот пример на c ++ (согласно сообщению), поскольку java действительно не поддерживает полиморфизм, поэтому трудно различить концепции в вопросе - person Lorenzo Boccaccia; 01.10.2008