Поліморфізм проти перекриття проти перевантаження


347

Що стосується Java, коли хтось запитує:

що таке поліморфізм?

Чи буде перевантаження чи переосмислення прийнятною відповіддю?

Я думаю, що в цьому є трохи більше.

ЯКЩО у вас був абстрактний базовий клас, який визначав метод без реалізації, і ви визначили цей метод у підкласі, це все-таки перевищує?

Я думаю, що перевантаження не є правильною відповіддю напевно.


Нижче відповіді дуже добре пояснюють поліморфізм. Але у мене є сильні заперечення сказати, що перевантаження - це тип поліморфізму, який я намагався обґрунтувати в своєму запитанні і відповісти, що насправді концентрується на перевантаженні - це поліморфізм чи ні. Я намагався обґрунтувати @The Digital Gabeg відповідь, присутня в цій темі. Посилання на розробку: Перевантаження методу - це статична зв'язка / час компіляції, але не поліморфізм. Чи правильно співвідносити статичне зв’язування з поліморфізмом?
PraveenKumar Lalasangi

Відповіді:


894

Найясніший спосіб виразити поліморфізм - через абстрактний базовий клас (або інтерфейс)

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
...

37
@yuudachi. Я придумав цей приклад, коли викладав клас. Канонічний клас "Банківський рахунок" насправді не виражав "абстрактність" базового класу. Інший канонічний приклад (Тварини, шуміть) був занадто абстрактним для розуміння. Я шукав єдину базу із занадто очевидними підкласами. Власне, goPee () був єдиним прикладом, який я придумав, що не був сексистським чи стереотипним. (хоча в класі я надрукував "вниз по залі ліворуч" замість того, щоб встати або сісти.)
Кріс Кадмор

100
Цей приклад також добре підкреслює труднощі використання ієрархічної системи для опису біологічних систем. Деякі люди, такі як зовсім маленькі, писять майже в будь-якому положенні - і немовлят не можуть легко сказати goPee (). Деякі люди є інтерсексами, де біологічні мітки "чоловічого" або "жіночого" стають досить погано визначеними; соціальні значення ще складніші. Як навчальний приклад, він показує, як припущення моделювання можуть мати негативні результати, наприклад, про те, що хтось (наприклад, студент програмування ОО), хто є інконтинентом або інтерсекс, насправді не є людиною.
Ендрю Далке

7
Я можу придумати принаймні жменю людей, які спростували б вашу тезу "ти не можеш створити людину, яка не є ні чоловіком, ні жінкою", хоча це все-таки буде правдою для твого коду ... погана абстракція, я думаю, я говорю ? ;)
Франк В. Замметті

2
Я думаю, що важливо зазначити, що це лише поліморфізм, тому яку версію goPee () викликати можна визначити лише під час виконання. Хоча цей приклад мав на увазі це, приємно зазначити, чому саме це поліморфізм. Крім того, для цього не потрібні заняття побратимів. Це можуть бути і відносини батько-дитина. Або навіть абсолютно не пов'язані між собою класи, які збігаються однаково. Прикладом цього може бути функція .toString (). Що можна назвати випадковим чином на будь-якому об’єкті, але компілятор ніколи не може точно знати, який тип об’єкта.
Tor Valamo

20
@AndrewDalke, +1 для приміток про біологічну складність. Крім того, goPeeне приймає гравітаційне поле як вхідне. Ця залежність від глобального стану ускладнює тестування одиниць CatheterizedIntersexAstronautі показує, що підкласифікація не завжди може бути найкращим методом для складання ознак.
Майк Самуель

99

Поліморфізм - це здатність класового екземпляра поводити себе так, ніби це екземпляр іншого класу у своєму спадковому дереві, найчастіше - одного з класів його предків. Наприклад, у Java всі класи успадковують від Object. Тому ви можете створити змінну типу Object і призначити їй примірник будь-якого класу.

перевизначенняце тип функції, що виникає в класі, який успадковується від іншого класу. Функція переосмислення "замінює" функцію, успадковану від базового класу, але робить це таким чином, що вона викликається навіть тоді, коли екземпляр її класу робить вигляд іншого типу через поліморфізм. Посилаючись на попередній приклад, ви могли б визначити свій власний клас та замінити функцію toString (). Оскільки ця функція успадкована від Object, вона все одно буде доступна, якщо скопіювати екземпляр цього класу в змінну типу Object. Зазвичай, якщо ви викликаєте toString () у своєму класі, поки він претендує на об'єкт, версія toString, яка насправді буде запускатись, є тією, що визначена в самому Object. Однак, оскільки функція є переопрацюванням, визначення toString () з вашого класу використовується навіть тоді, коли екземпляр класу '

Перевантаження - це дія визначення декількох методів з однаковою назвою, але з різними параметрами. Це не пов'язано ні з переважаючим, ні з поліморфізмом.


8
Це старе, але поліморфізм не означає, що інший клас повинен бути у дереві спадкування. Це робиться в Java, якщо ви вважаєте, що інтерфейси є частиною дерева спадкування, але не в Go, де інтерфейси реалізовані неявно.
JN

5
Насправді, заняття з поліморфізму взагалі не потрібні.
StCredZero

3
Я новачок, і виправте мене, якщо я помиляюся, але я б не сказав, що перевантаження не пов'язане з поліморфізмом. Принаймні, на Java поліморфізм - це коли реалізація вибирається виходячи з типу абонента, а перевантаження - це коли реалізація вибирається виходячи з типу параметрів, чи не так? Бачити подібність між цими двома допомагає мені зрозуміти це.
csjacobs24

9
Неправильно. Ad hoc polymorphismце те, що ви описали в розділі « Перевантаження» і є випадком поліморфізму.
Джоссі Кальдерон

1
"Це не пов'язано ні з переважаючим, ні з поліморфізмом". Це твердження неправильне.
Шайлеш Пратапвар

45

Поліморфізм означає більш ніж одну форму, один і той же об’єкт, що виконує різні операції відповідно до вимоги.

Поліморфізм можна досягти, використовуючи два способи, такі

  1. Перевизначення методу
  2. Метод перевантаження

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

Перевизначення методу означає, що ми використовуємо назви методів у різних класах, це означає, що метод батьківського класу використовується в дочірньому класі.

У Java для досягнення поліморфізму опорна змінна величина класу може містити об'єкт підкласу.

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


4
+1 за гарну відповідь. Прийнята відповідь пояснює лише один тип поліморфізму. Ця відповідь завершена.
apadana

1
поліморфізм є парадигмою (OOP), але переосмислення та перевантаження є мовними засобами.
曾 其 威

Поліморфізм може бути досягнутий і за родовим типом.
Minh Nghĩa

43

Ось приклад поліморфізму в псевдо-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 ().

Правка: Схоже, Брайан побив мене на удар. Смішно, ми використовували той же приклад. Але наведений вище код повинен допомогти уточнити поняття.


Це приклад поліморфізму виконання. Поліморфізм у часі компіляції можливий також за допомогою методів перевантаження та родових типів.
Піт Кіркхем

Форма -> Паралелограма -> Прямокутник -> Квадрат
вр.

@ yankee2905 в цьому випадку, я думаю, ви можете використовувати інтерфейси, оскільки клас може реалізувати декілька інтерфейсів.
Sam003

1
@Zhisheng Або додати метод pee в абстрактний батьківський клас? Я б використовував інтерфейс, щоб реалізувати щось інше.
joey rohan

43

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

У вас може бути метод у класі, який перекрито в одному або декількох підкласах. Метод робить різні речі залежно від того, який клас використовувався для екземпляра об'єкта.

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

Я припускаю, що це було проголошено, оскільки перевантаження методом історично не вважається частиною поліморфізму в об'єктно-орієнтованій парадигмі. Перевантаження методу та поліморфізм - це дві ортогональні, незалежні особливості мови програмування.
Серхіо Акоста

7
Як я заявив у своїй відповіді тут, я не згоден - дві риси не є ортогональними, але тісно пов'язані. Поліморфізм! = Спадкування. У вас є моє голосування.
Пітер Мейер

2
Іншими словами, введіть поліморфізм проти спеціального поліморфізму. Я підтримую цю відповідь, навіть якщо вона не така повна, як слід, тому що вона правильно стверджує, що і перевантаження, і переоцінка пов'язані з поліморфізмом. Сказати, що поліморфізм у мовах OOP може бути досягнутий лише за допомогою успадкування класів - просто неправильно - слід пам’ятати, що крім Java та C ++ є ще деякі мови OOP, де можна використовувати такі поняття, як багаторазова диспетчеризація, спеціальний поліморфізм, параметричний поліморфізм тощо .
rsenna

2
@rsenna Це може бути неповним, але він відповідає на питання набагато краще, ніж решта IMHO. Також дуже приємно, що ви згадали про спеціальний та параметричний поліморфізм.
Валентин Раду

15

Ви вірні, що перевантаження - це не відповідь.

Жоден з них не переважає. Переоцінка - це засіб, за допомогою якого ви отримуєте поліморфізм. Поліморфізм - це здатність об’єкта змінювати поведінку залежно від його типу. Це найкраще демонструється, коли абонент об'єкта, який виявляє поліморфізм, не знає, який саме тип є об'єктом.


3
Змінюється не поведінка об'єкта, а його реалізація. Одна і та ж поведінка, інша реалізація, це поліморфізм.
QBziZ

@QBziZ Вам потрібно визначити поведінку , особливо прикметник той самий . Якщо поведінка однакова, чому їхня реалізація повинна бути різною? Справа не в тому, що хтось незадоволений певною реалізацією, тому вимагає іншого.
Snađошƒаӽ

11

Зокрема, перевантаження або переосмислення не дає повного уявлення. Поліморфізм - це просто здатність об’єкта спеціалізувати свою поведінку виходячи з його типу.

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

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


Ви маєте рацію щодо того, що означають слова, що стосуються загалом, але в контексті програмування, коли люди кажуть "поліморфізм", вони завжди означають "поліморфізм, заснований на спадщині". Цікавий момент, але я думаю, що описуючи поліморфізм таким чином збентежить людей.
Цифровий Габег

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

4
Щоб було зрозуміло, я думаю, що різні форми повинні бути викладені - чого я навіть не адекватно зробив - тому що тут є кілька відповідей, які подаються як абсолютні. Я з повагою не погоджуюся з тим, що в "програмістському контексті ..." поліморфізм "завжди означає" поліморфізм, заснований на спадщині ""
Пітер Мейер

2
Я думаю , що перевантаження краще класифікується як Ad-hoc_polymorphism en.wikipedia.org/wiki / ...
Ману

Я схильний погоджуватися з «Цифровим Габегом» щодо наступного. Якщо ви обговорюєте ООП, поліморфізм зазвичай означає підтиповий поліморфізм, а якщо ви обговорюєте теорію типів, це означає будь-який тип поліморфізму. Але, як ви кажете, з "контекстом програміста" це надто неоднозначно.
Ману

7

Поліморфізм просто означає "Багато форм".

Він не вимагає успадкування для досягнення ... оскільки реалізація інтерфейсу, яка зовсім не є спадщиною, задовольняє поліморфні потреби. Можливо, реалізація інтерфейсу служить поліморфним потребам "Краще", ніж успадкуванню.

Наприклад, ви створили б суперклас, щоб описати всі речі, які можуть літати? Я повинен думати, що ні. Вам було б найкраще створити інтерфейс, який описує політ і залишити його при цьому.

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


2
Однозначно найкраща відповідь поки. Поліморфізм може застосовуватися до всіх мовних конструкцій, будь то іменники (класи) або дієслова (методи).
Раду Гаслер

6

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

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

Ось що я вважаю поліморфізмом.


4

Поліморфізм - це здатність об’єкта з’являтися в декількох формах. Це передбачає використання успадкування та віртуальних функцій для побудови сімейства об'єктів, які можуть бути замінені. Базовий клас містить прототипи віртуальних функцій, можливо, без змін або з реалізацією за замовчуванням, як диктує додаток, і різні похідні класи кожен реалізує їх по-різному, щоб впливати на різну поведінку.


4

Ні:

Перевантаження - це те, що у вас однакова назва функції, яка приймає різні параметри.

Переосмислення - це коли дочірній клас замінює батьківський метод одним із власних (це саме по собі не є поліморфізмом).

Поліморфізм запізнюється, наприклад, викликаються методи базового класу (батьківські), але не доки програма не дізнається, що саме є об'єктом - це може бути дочірній клас, методи якого відрізняються. Це тому, що будь-який дочірній клас може використовуватися там, де визначено базовий клас.

У Java ви бачите багато поліморфізму з бібліотекою колекцій:

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

Список є базовим класом, компілятор не має поняття, якщо ви рахуєте пов'язаний список, вектор, масив або реалізацію користувацького списку, якщо він діє як список:

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

Якщо ви перевантажувались, вам доведеться:

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

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


4

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

Чому поліморфізм настільки важливий у будь-якій мові ООП.

Спробуємо побудувати простий додаток для телевізора з і без наслідування / поліморфізму. Опублікувавши кожну версію програми, ми робимо невелику ретроспективу.

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

Ви починаєте з занять з написання для кожної з цих функцій, додаючи

  1. set: - Встановити значення контролера. (припустимо, що в ньому є специфічний код контролера)
  2. get: - Отримати значення контролера. (Припустимо, він має специфічний код контролера)
  3. Налаштування: - Для перевірки введення та встановлення контролера (загальні перевірки .. незалежно від контролерів)
  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) код дублюється у всіх трьох класах. Ви хочете мінімізувати подвійність коду. (Але ви не думали про загальний код та переміщення його до якогось суперкласу, щоб уникнути дублювання коду)

Ви вирішили жити з цим до тих пір, поки ваша програма працює, як очікувалося.

Після цього ваш бос повертається до вас і просить додати функцію скидання до існуючої програми. Скидання встановило б усі три контролера на їх значення за замовчуванням.

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

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

Тепер ви починаєте думати, що ця нова функція, яку потрібно додати, нагадує функцію Скидання, а проблеми програми (V2) будуть помножені, якщо ви не перефактуруєте свою програму.

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

  1. Оголосіть підпис методу get and 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. Скинути функціональний клас (ResetFunctionV3) може отримати доступ до іншого методу класу Controller (коригування), який небажаний.

Знову ж таки, ви думаєте вирішити цю проблему, оскільки тепер у вас є ще одна функція (оновлення драйверів при запуску). Якщо цього не виправити, він також буде тиражуватися на нові функції.

Отже, ви розділите договір, визначений на абстрактний клас, і напишіть 2 інтерфейси для

  1. Функція скидання.
  2. Оновлення драйверів.

І ваш перший бетонний клас реалізує їх, як показано нижче

Версія програми 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 контролерів)

Сподіваюся, це допомагає :-)


3

Термін перевантаження відноситься до наявності декількох версій чогось одного і того ж імені, як правило, методів з різними списками параметрів

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

Таким чином, ці функції можуть робити те саме, але у вас є можливість викликати його ідентифікатором або іменем. Не має нічого спільного з успадкуванням, абстрактними класами тощо.

Переоцінка зазвичай стосується поліморфізму, як ви описали у своєму запитанні


2

перевантаження - це коли ви визначаєте 2 методи з однаковою назвою, але різними параметрами

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

Тож поліморфізм пов'язаний з переважаючим, але насправді не перевантажувальним.

Однак якщо хтось дав мені просту відповідь "переосмислити" на питання "Що таке поліморфізм?" Я б просив додаткових пояснень.


2

переопределення більше схоже на приховування успадкованого методу шляхом оголошення способу з тим же ім'ям та підписом, як метод верхнього рівня (супер метод), це додає поліморфної поведінки класу. Іншими словами, рішення про вибір методу рівня для виклику буде прийнято під час виконання, а не під час компіляції. це призводить до концепції інтерфейсу та реалізації.


2

що таке поліморфізм?

З підручника 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:

2

Я думаю, хлопці, ваші змішують поняття. Поліморфізм - це здатність об’єкта поводитись по-різному під час руху. Для цього вам потрібно два реквізити:

  1. Пізнє зв’язування
  2. Спадщина.

Сказавши, що перевантаження означає щось інше, ніж переосмислення, залежно від мови, якою ви користуєтесь. Наприклад, у Java не існує перекриття, а перевантаження . Перенавантажені методи з різним підписом до його базового класу доступні в підкласі. Інакше вони будуть відмінені (будь ласка, дивіться, що я маю на увазі факт, що немає способу викликати ваш метод базового класу поза об'єктом)

Однак у С ++ це не так. Будь-який перевантажений метод, незалежно від того, підпис однаковий чи ні (різний розмір, різний тип), також буде перекрито . Тобто на сьогоднішній день метод базового класу більше не доступний у підкласі, коли викликається з-під об'єкта підкласу, очевидно.

Тож відповідь, коли ми говоримо про перевантаження Java використанням . У будь-якій іншій мові це може бути різним, як це відбувається в c ++


1

Поліморфізм швидше, наскільки це стосується його сенсу ... НАДОБРЕННЯ в java

Вся справа в різній поведінці об'єкта SAME в різних ситуаціях (У програмуванні ... ви можете викликати різні АРГУМЕНТИ)

Я думаю, що наведений нижче приклад допоможе вам зрозуміти ... Хоча це не ЧИСТИЙ код Java ...

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

Але якщо ми змінимо АРГУМЕНТ ... ПОВЕДІНКА буде змінена ...

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

Особа (тут "Об'єкт") така ж ...


1

Поліморфізм - це декілька реалізацій об'єкта або, можна сказати, декількох форм об'єкта. скажемо, у вас клас Animalsяк абстрактний базовий клас, і він має метод, movement()який називається, який визначає шлях руху тварини. Зараз насправді у нас є різні види тварин, і вони рухаються по-різному, а також деякі з двома ногами, інші - з 4, а інші - без ніг тощо. Для визначення різних movement()тварин на землі нам потрібно застосувати поліморфізм. Однак вам потрібно визначити більше класів, тобто клас Dogs Cats Fishтощо. Тоді вам потрібно розширити ці класи з базового класу Animalsі замінити його метод movement()новим функціональним рухом на основі кожної тварини. Ви також можете використовуватиInterfacesщоб досягти цього. Ключове слово тут є переважаючим, перевантаження є різною і не розглядається як поліморфізм. при перевантаженні ви можете визначити кілька методів "з тим самим іменем", але з різними параметрами для одного об'єкта або класу.


0

Поліморфізм відноситься до здатності мови по-різному обробляти різні об'єкти за допомогою одного інтерфейсу; як такий він пов'язаний з перекриттям, тому інтерфейс (або базовий клас) є поліморфним, реалізатором є об'єкт, який переосмислює (дві грані однієї медалі)

у будь-якому випадку, різницю між двома термінами краще пояснити за допомогою інших мов, таких як 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 справді не пропонує такого рівня поліморфізму (його також називають нарізкою об'єктів).

тварина а = нова собака (); собака b = нова собака ();

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

в обох випадках він буде друкувати тільки woff .. оскільки a і b переглядає класу собака



тварина а = нова собака (); a був побудований як собака, і буде друкувати "woff". Якщо ви хочете, щоб він надрукував палець, вам потрібно його підняти. ((Тварина) а) .makeRumor ()
Кріс Кадмор

Це посилання на оновлення, але об'єктом все ще є собака. Якщо ви хочете, щоб це була тварина, ви повинні явно поновити об’єкт.
Кріс Кадмор

Зрозумів це. Питання було позначено Java. Ви відповіли на C ++. Ви можете бути правильними на C ++. Я напевно правильно в Java.
Кріс Кадмор

має відбуватися кожного разу, коли тут задіяний конструктор копій - це посилання fredosaurus.com/notes-cpp/oop-condestructors/…, випадок три збіги; ігноруйте нового оператора, який існує лише для розмежування створення.
Лоренцо Боккачча

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

    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.