web-dev-qa-db-fra.com

Polymorphisme vs neutralisation vs surcharge

En termes de Java, quand quelqu'un demande:

qu'est-ce que le polymorphisme?

Est-ce que surcharge ou annulation serait une réponse acceptable?

Je pense qu'il y a un peu plus que cela.

SI vous aviez une classe de base abstraite qui a défini une méthode sans implémentation et que vous avez défini cette méthode dans la sous-classe, cela est-il toujours prioritaire?

Je pense que surcharge n'est pas la bonne réponse à coup sûr.

332
Brian G

Le moyen le plus clair d’exprimer le polymorphisme est via une classe de base abstraite (ou une interface)

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

Cette classe est abstraite car la méthode goPee() ne peut pas être définie pour Humans. Il n'est définissable que pour les sous-classes Male et Female. En outre, l'humain est un concept abstrait - Vous ne pouvez pas créer un humain qui ne soit ni homme ni femme. Il faut que ce soit l'un ou l'autre.

Nous reportons donc l'implémentation en utilisant la classe abstraite.

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

et

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

Maintenant, nous pouvons dire à toute une pièce remplie d'humains d'aller faire pipi.

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

Courir cela donnerait:

Stand Up
Sit Down
...
875
Chris Cudmore

Polymorphisme est la capacité d'une instance de classe à se comporter comme s'il s'agissait d'une instance d'une autre classe de son arbre d'héritage, le plus souvent une de ses classes ancêtres. Par exemple, dans Java, toutes les classes héritent de Object. Par conséquent, vous pouvez créer une variable de type Object et lui attribuer une instance de n'importe quelle classe.

Un override est un type de fonction qui survient dans une classe qui hérite d'une autre classe. Une fonction de substitution "remplace" une fonction héritée de la classe de base, mais le fait de manière à ce qu'elle soit appelée même lorsqu'une instance de sa classe prétend être un type différent par polymorphisme. En vous référant à l'exemple précédent, vous pouvez définir votre propre classe et remplacer la fonction toString (). Cette fonction étant héritée d'Object, elle sera toujours disponible si vous copiez une instance de cette classe dans une variable de type Object. Normalement, si vous appelez toString () sur votre classe alors qu'elle prétend être un objet, la version de toString qui sera déclenchée est celle définie sur Object lui-même. Toutefois, comme la fonction est un remplacement, la définition de toString () de votre classe est utilisée même lorsque le type réel de l'instance de la classe est masqué derrière un polymorphisme.

surcharge est l’action de définition de plusieurs méthodes portant le même nom mais avec des paramètres différents. Il n’est pas lié à la dominance ni au polymorphisme.

92
The Digital Gabeg

Voici un exemple de polymorphisme en pseudo-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 ());
}

La fonction Main ne connaît pas le type de l'animal et dépend du comportement de la méthode MakeNoise () dans une implémentation particulière.

Edit: On dirait que Brian m'a battu au coup de poing. Drôle nous avons utilisé le même exemple. Mais le code ci-dessus devrait aider à clarifier les concepts.

43
Mark A. Nicolosi

Polymorphisme signifie plus d'une forme, le même objet effectuant différentes opérations en fonction des besoins.

Le polymorphisme peut être obtenu de deux manières différentes:

  1. Méthode prioritaire
  2. Méthode surchargée

Surcharge de méthode signifie écrire deux ou plusieurs méthodes de la même classe en utilisant le même nom de méthode, mais les paramètres de passage sont différents.

Méthode surchargée signifie que nous utilisons les noms de méthodes dans les différentes classes, ce qui signifie que la méthode de la classe parent est utilisée dans la classe enfant.

Dans Java pour réaliser le polymorphisme, une variable de référence de super classe peut contenir l'objet de la sous-classe.

Pour réaliser le polymorphisme, chaque développeur doit utiliser les mêmes noms de méthodes dans le projet.

43
manoj

La surcharge et la surcharge sont toutes deux utilisées pour obtenir un polymorphisme.

Vous pourriez avoir une méthode dans une classe qui est substituée dans une ou plusieurs sous-classes. La méthode fait différentes choses selon la classe utilisée pour instancier un objet.

    abstract class Beverage {
       boolean isAcceptableTemperature();
    }

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

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

Vous pouvez également avoir une méthode surchargée avec deux jeux d'arguments ou plus. La méthode fait différentes choses en fonction du type d'argument (s) passé (s).

    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);
        }
    }
39
Patrick McElhaney

Vous avez raison, la surcharge n'est pas la solution.

Ni est primordial. La neutralisation est le moyen par lequel vous obtenez un polymorphisme. Le polymorphisme est la capacité d'un objet à modifier le comportement en fonction de son type. Ceci est mieux démontré lorsque l'appelant d'un objet présentant un polymorphisme ignore le type spécifique de cet objet.

13
Alex B

Dire spécifiquement que la surcharge ou le dépassement ne donne pas une image complète. Le polymorphisme est simplement la capacité d'un objet à spécialiser son comportement en fonction de son type.

Je ne suis pas d’accord avec certaines des réponses fournies ici car la surcharge est une forme de polymorphisme (polymorphisme paramétrique) dans le cas où une méthode portant le même nom peut se comporter différemment et donner des types de paramètre différents. Un bon exemple est la surcharge de l'opérateur. Vous pouvez définir "+" pour accepter différents types de paramètres - par exemple des chaînes de caractères ou des entiers - et en fonction de ces types, "+" se comportera différemment.

Le polymorphisme inclut également les méthodes d'héritage et de substitution, bien qu'elles puissent être abstraites ou virtuelles dans le type de base. En termes de polymorphisme basé sur l'héritage, Java ne prend en charge que l'héritage d'une classe unique, limitant ainsi le comportement polymorphe à celui d'une chaîne unique de types de base. Java prend en charge la mise en œuvre de plusieurs interfaces, ce qui constitue une autre forme de comportement polymorphe.

10
Peter Meyer

Polymorphisme signifie simplement "nombreuses formes".

L'héritage n'est pas OBLIGATOIRE pour que ... car l'implémentation d'interface, qui n'est pas du tout l'héritage, répond aux besoins polymorphes. On peut soutenir que l'implémentation d'interface répond aux besoins polymorphes "mieux" que l'héritage.

Par exemple, créeriez-vous une super-classe pour décrire tout ce qui peut voler? Je devrais penser non. Vous seriez mieux servi pour créer une interface qui décrit le vol et en rester là.

Ainsi, étant donné que les interfaces décrivent le comportement et que les noms de méthode décrivent le comportement (pour le programmeur), il n’est pas exagéré de considérer la surcharge de méthode comme une forme moindre de polymorphisme.

7
BillC

L'exemple classique, les chiens et les chats sont des animaux, les animaux ont la méthode makeNoise. Je peux parcourir une série d'animaux appelant makeNoise sur eux et m'attendre à ce qu'ils se chargent de leur mise en œuvre respective.

L'indicatif d'appel n'a pas besoin de savoir de quel animal il s'agit.

C’est ce que je pense être un polymorphisme.

6
Brian G

Ni:

La surcharge se produit lorsque vous avez le même nom de fonction qui prend des paramètres différents.

La substitution a lieu lorsqu'une classe enfant remplace la méthode d'un parent par l'une des siennes (cela ne constitue pas en soi un polymorphisme).

Le polymorphisme est une liaison tardive, par ex. les méthodes de la classe de base (parent) sont appelées, mais pas avant que l'application ne sache en quoi consiste l'objet; il peut s'agir d'une classe enfant dont les méthodes sont différentes. En effet, toute classe enfant peut être utilisée lorsqu'une classe de base est définie.

Dans Java, vous voyez beaucoup de polymorphisme dans la bibliothèque de collections:

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

List est la classe de base, le compilateur n'a aucune idée si vous comptez une implémentation de liste liée, de vecteur, de tableau ou personnalisée, tant qu'elle se comporte comme une liste:

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

Si vous surchargiez vous auriez:

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

et la version correcte de countStuff () serait choisie par le compilateur pour correspondre aux paramètres.

4
jpeacock

Le polymorphisme est la capacité pour un objet d'apparaître sous plusieurs formes. Cela implique l'utilisation de l'héritage et des fonctions virtuelles pour créer une famille d'objets pouvant être échangés. La classe de base contient les prototypes des fonctions virtuelles, éventuellement non implémentées ou implémentées par défaut, comme le veut l'application, et les différentes classes dérivées les implémentent différemment pour affecter différents comportements.

4
mxg

Le terme surcharge désigne le fait d'avoir plusieurs versions d'un même nom, généralement des méthodes avec des listes de paramètres différentes

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

Donc, ces fonctions peuvent faire la même chose mais vous avez la possibilité de l’appeler avec un identifiant ou un nom. N'a rien à voir avec l'héritage, les classes abstraites, etc.

Remplacer fait généralement référence au polymorphisme, comme vous l'avez décrit dans votre question.

3
Clyde

Je pense que vous mélangez des concepts. Polymorphisme est la capacité d'un objet à se comporter différemment au moment de l'exécution. Pour ce faire, vous avez besoin de deux éléments indispensables:

  1. Liaison tardive
  2. héritage.

Cela dit surcharge signifie quelque chose de différent de priorité selon la langue que vous utilisez. Par exemple, dans Java n'existe pas substitution mais surcharge. Surchargé des méthodes avec une signature différente de la classe de base sont disponibles dans la sous-classe. Sinon, ils seraient surchargés (s'il vous plaît, voyez ce que je veux dire maintenant, le fait qu'il n'y ait aucun moyen d'appeler votre méthode de classe de base de l'extérieur de l'objet).

Cependant, en C++, ce n'est pas le cas. N'importe quelle méthode surchargée, que la signature soit identique ou non (montant différent, type différent) l'est également remplacée. C’est-à-dire qu’aujourd’hui, la méthode de la classe de base n’est plus disponible dans la sous-classe lorsqu’elle est appelée de l’extérieur de l’objet sous-classe, évidemment.

La réponse est donc lorsque vous parlez de Java use surcharge. Dans n'importe quel autre langage peut être différent de ce qu'il se passe en c ++

2
user1154840

Bien que le polymorphisme soit déjà expliqué en détail dans ce post, mais je voudrais mettre davantage l'accent sur pourquoi une partie de celui-ci.

Pourquoi le polymorphisme est-il si important dans n'importe quel langage OOP?.

Essayons de construire une application simple pour un téléviseur avec et sans héritage/polymorphisme. Après chaque version de l'application, nous faisons une petite rétrospective.

Supposons que vous êtes un ingénieur en logiciel dans une entreprise de télévision et qu'il vous est demandé d'écrire un logiciel pour les contrôleurs de volume, de luminosité et de couleur afin d'augmenter et de diminuer leurs valeurs sur commande de l'utilisateur.

Vous commencez par écrire des cours pour chacune de ces fonctionnalités en ajoutant

  1. set: - Pour définir la valeur d'un contrôleur (en supposant que ce code ait un code spécifique).
  2. get: - Pour obtenir la valeur d'un contrôleur (en supposant que celui-ci ait un code spécifique au contrôleur).
  3. ajuster: - Pour valider l'entrée et la configuration d'un contrôleur (validations génériques .. indépendantes des contrôleurs)
  4. mappage des entrées utilisateur avec les contrôleurs: - Pour obtenir les entrées utilisateur et appeler les contrôleurs en conséquence.

Version d'application 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;
        }

    }
    }
}

Maintenant, vous avez notre première version de l'application de travail prête à être déployée. Il est temps d'analyser le travail accompli jusqu'à présent.

Problèmes liés à l'application TV version 1

  1. Le code Adjust (int) est dupliqué dans les trois classes. Vous souhaitez minimiser la duplicité du code. (Mais vous n'avez pas pensé au code commun et ne l'avez pas déplacé dans une classe supérieure pour éviter le code en double)

Vous décidez de vivre avec cela tant que votre application fonctionne comme prévu.

Après parfois, votre patron revient à vous et vous demande d'ajouter une fonctionnalité de réinitialisation à l'application existante. Réinitialiser définirait les trois trois contrôleurs à leurs valeurs par défaut respectives.

Vous commencez à écrire une nouvelle classe (ResetFunctionV2) pour la nouvelle fonctionnalité et mappez le code de mappage d'entrée de l'utilisateur pour cette nouvelle fonctionnalité.

Version d'application 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;
            }

        }
    }
}

Vous avez donc votre application prête avec la fonction de réinitialisation. Mais maintenant, vous commencez à réaliser que

Problèmes liés à l'application TV version 2

  1. Si un nouveau contrôleur est introduit dans le produit, vous devez modifier le code de fonction de réinitialisation.
  2. Si le nombre de contrôleurs devient très élevé, vous auriez de la difficulté à conserver les références des contrôleurs.
  3. Le code de fonction de réinitialisation est étroitement associé à tous les codes de la classe des contrôleurs (pour obtenir et définir les valeurs par défaut).
  4. La fonction de réinitialisation (ResetFunctionV2) peut accéder à une autre méthode indésirable (ajuster).

Dans le même temps, Boss, vous indiquez que vous devrez peut-être ajouter une fonctionnalité permettant à chacun des contrôleurs, au démarrage, de rechercher la dernière version du pilote dans le référentiel de pilotes hébergé de la société via Internet.

Maintenant, vous commencez à penser que cette nouvelle fonctionnalité à ajouter ressemble à la fonctionnalité Réinitialiser et que les Problèmes d’application (V2) seront multipliés si vous ne re-factorisez pas votre application.

Vous commencez à penser à utiliser l’héritage pour pouvoir tirer parti de la capacité polymorphe de Java et vous ajoutez une nouvelle classe abstraite (ControllerV3) à

  1. Déclarez la signature de la méthode get and set.
  2. Contient l'implémentation de la méthode de réglage qui a été précédemment répliquée sur tous les contrôleurs.
  3. Déclarez la méthode setDefault afin que la fonctionnalité de réinitialisation puisse être facilement implémentée en utilisant Polymorphism.

Avec ces améliorations, vous avez la version 3 de votre application TV prête à l'emploi.

Version d'application 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;
            }

        }
    }
}

Bien que la plupart des problèmes énumérés dans la liste des problèmes de la V2 aient été résolus, sauf

Problèmes liés à l'application TV version 3

  1. La fonction de réinitialisation (ResetFunctionV3) peut accéder à une autre méthode indésirable (ajuster).

Encore une fois, vous songez à résoudre ce problème, car vous avez maintenant une autre fonctionnalité (mise à jour du pilote au démarrage) à implémenter également. Si vous ne le corrigez pas, il sera également répliqué dans les nouvelles fonctionnalités.

Donc, vous divisez le contrat défini en classe abstraite et écrivez 2 interfaces pour

  1. Fonction de réinitialisation.
  2. Mise à jour du pilote.

Et demandez à votre 1ère classe de béton de les mettre en œuvre comme ci-dessous

Version d'application 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;
            }

        }
    }
}

Maintenant, tous les problèmes que vous avez rencontrés ont été résolus et vous vous êtes rendu compte qu'avec l'utilisation de l'héritage et du polymorphisme, vous pourriez

  1. Conservez les différentes parties de l'application sans les coupler (les composants de la réinitialisation ou de la mise à jour du pilote n'ont pas besoin d'être informés des classes de contrôleurs réelles (Volume, luminosité et couleur), toute classe implémentant OnReset ou OnStart sera acceptable pour la fonction de réinitialisation ou de mise à jour du pilote. composants respectifs).
  2. L’amélioration de l’application devient plus facile (un nouvel ajout de contrôleur n’a pas d’incidence sur la réinitialisation ou le composant de fonctionnalité de mise à jour du pilote, il est désormais très facile d’en ajouter de nouveaux).
  3. Conserver la couche d'abstraction. (La fonction Réinitialiser ne peut désormais voir que la méthode setDefault des contrôleurs et la fonction Réinitialiser ne peut voir que la méthode checkForDriverUpdate des contrôleurs)

J'espère que cela t'aides :-)

2
Developer

qu'est-ce que le polymorphisme?

De Java tutoriel

La définition du polymorphisme dans le dictionnaire fait référence à un principe de la biologie selon lequel un organisme ou une espèce peut avoir de nombreuses formes ou étapes. Ce principe peut également être appliqué à la programmation orientée objet et à des langages tels que le langage Java. Les sous-classes d'une classe peuvent définir leurs propres comportements uniques tout en partageant certaines des mêmes fonctionnalités de la classe parente.

En considérant les exemples et la définition, écrasant devrait être accepté comme réponse.

Concernant votre seconde requête:

SI vous aviez une classe de base abstraite qui a défini une méthode sans implémentation, et que vous avez défini cette méthode dans la sous-classe, cela est-il toujours négatif?

Il faut appeler cela prioritaire.

Regardez cet exemple pour comprendre différents types de dépassement.

  1. La classe de base ne fournit aucune implémentation et la sous-classe doit écraser la méthode complete - (résumé)
  2. La classe de base fournit une implémentation par défaut et la sous-classe peut changer le comportement
  3. La sous-classe ajoute une extension à l'implémentation de la classe de base en appelant super.methodName() comme première instruction
  4. La classe de base définit la structure de l'algorithme (méthode Template) et la sous-classe écrasera une partie de l'algorithme

extrait de code:

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

sortie:

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
Ravindra babu

la surcharge est lorsque vous définissez 2 méthodes avec le même nom mais des paramètres différents

la substitution est l'endroit où vous modifiez le comportement de la classe de base via une fonction du même nom dans une sous-classe.

Le polymorphisme est donc lié au dépassement mais pas vraiment à la surcharge.

Cependant, si quelqu'un me donnait une simple réponse "écrasante" à la question "Qu'est-ce que le polymorphisme?" Je demanderais des explications supplémentaires.

2
Matt

redéfinir revient à cacher une méthode héritée en déclarant une méthode avec le même nom et la même signature que la méthode de niveau supérieur (super méthode), cela ajoute un comportement polymorphe à la classe. autrement dit, la décision de choisir la méthode de niveau à appeler sera prise au moment de l'exécution et non au moment de la compilation. Cela conduit au concept d'interface et de mise en œuvre.

2
Genjuro

Le polymorphisme est plus probable en ce qui concerne signification est concerné ... au dépassement en Java

Il s’agit de comportements différents de l’objet SAME dans différentes situations (en programmation ... vous pouvez appeler différents arguments)

Je pense que l'exemple ci-dessous vous aidera à comprendre ... Bien que ce ne soit pas du code PURE Java ...

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

Mais si nous changeons l'ARGUMENT ... le COMPORTEMENT sera changé ...

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

La personne (ici "l'objet") est la même ...

1
Rajan

Le polymorphisme est une multiple implémentation d'un objet ou vous pouvez dire plusieurs formes d'un objet. Disons que vous avez la classe Animals comme classe de base abstraite et une méthode appelée movement() qui définit la façon dont l'animal se déplace. Maintenant, en réalité, nous avons différents types d'animaux et ils se déplacent différemment, certains avec 2 pattes, d'autres avec 4 pattes et d'autres sans pattes, etc. Pour définir différents movement() de chaque animal sur terre, nous devons appliquer un polymorphisme. Cependant, vous devez définir plus de classes, à savoir la classe DogsCatsFish etc. Vous devez ensuite étendre ces classes à partir de la classe de base Animals et remplacer sa méthode movement() par un nouvelle fonctionnalité de mouvement basée sur chaque animal que vous avez. Vous pouvez également utiliser Interfaces pour y parvenir. Le mot clé ici est primordial, la surcharge est différente et n'est pas considérée comme un polymorphisme. en cas de surcharge, vous pouvez définir plusieurs méthodes "avec le même nom" mais avec des paramètres différents sur le même objet ou la même classe.

1
SolidSnake

Le polymorphisme concerne la capacité d'un langage à traiter différents objets de manière uniforme en utilisant une seule interface. en tant que tel, il est lié au remplacement, l'interface (ou la classe de base) est donc polymorphe, l'implémenteur est l'objet qui annule (deux faces de la même médaille).

de toute façon, la différence entre les deux termes est mieux expliquée à l'aide d'autres langages, tels que c ++: un objet polymorphe en c ++ se comporte comme la contrepartie Java si la fonction de base est virtuelle, mais si la méthode n'est pas virtuelle le saut de code est résolu statiquement, et le type réel n'étant pas vérifié au moment de l'exécution, le polymorphisme inclut la possibilité pour un objet de se comporter différemment selon l'interface utilisée pour y accéder; laissez-moi vous donner un exemple en pseudocode:

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

(en supposant que makeRumor n'est PAS virtuel)

Java n'offre pas vraiment ce niveau de polymorphisme (appelé également découpage d'objet).

animal a = nouveau chien (); chien b = nouveau chien ();

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

dans les deux cas, il ne fera qu'imprimer woff .. car a et b font référence à dog class

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

    }
}
0
bharanitharan