Polymorphisme vs Surcharge vs Surcharge

347

En termes de Java, quand quelqu'un demande:

qu'est-ce que le polymorphisme?

Serait en surcharge ou outrepasser serait-il une réponse acceptable?

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

SI vous aviez une classe de base abstraite qui définissait une méthode sans implémentation et que vous définissiez cette méthode dans la sous-classe, est-ce toujours une surcharge?

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

Brian G
la source
Les réponses ci-dessous expliquent très bien le polymorphisme. Mais j'ai une forte objection à dire que la surcharge est un type de polymorphisme, que j'ai essayé de justifier dans ma question et réponse qui se concentre réellement sur la surcharge est le polymorphisme ou non. J'ai essayé de justifier la réponse @The Digital Gabeg présente dans ce fil. Reportez-vous à l' élaboration: la surcharge de méthode est une liaison statique / au moment de la compilation, mais pas un polymorphisme. Est-il correct de corréler la liaison statique avec le polymorphisme?
PraveenKumar Lalasangi

Réponses:

894

La façon la plus claire d'exprimer le polymorphisme est via une classe de base abstraite (ou interface)

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

Cette classe est abstraite car la goPee() méthode n'est pas définissable pour les humains. Il n'est définissable que pour les sous-classes Homme et Femme. De plus, l'humain est un concept abstrait - vous ne pouvez pas créer un humain qui n'est ni masculin ni féminin. Ça doit être 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 à une salle entière 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();
}

L'exécution de cela donnerait:

Stand Up
Sit Down
...
Chris Cudmore
la source
37
@yuudachi. J'ai trouvé cet exemple en enseignant une classe. La classe canonique "Bank Account" n'exprimait pas vraiment le "caractère abstrait" de la classe de base. L'autre exemple canonique (Animal, faire du bruit) était trop abstrait pour être compris. Je cherchais une seule base avec des sous-classes trop évidentes. En fait, goPee () était le seul exemple que j'ai trouvé qui n'était ni sexiste ni stéréotypé. (bien qu'en classe, j'ai imprimé "dans le couloir à gauche" au lieu de me lever ou de m'asseoir.)
Chris Cudmore
100
Cet exemple met également en évidence la difficulté d'utiliser un système hiérarchique pour décrire les systèmes biologiques. Certains humains, comme les très jeunes, font pipi dans presque toutes les positions - et on ne peut pas facilement dire aux bébés de goPee (). Certains humains sont intersexués, où les étiquettes biologiques de «mâle» ou «femelle» deviennent plutôt mal définies; les significations sociales sont encore plus complexes. À titre d'exemple pédagogique, il montre comment les hypothèses de modélisation peuvent avoir des résultats négatifs, comme l'implication qu'une personne (par exemple, un étudiant en programmation OO) incontinente ou intersexuée n'est pas réellement humaine.
Andrew Dalke
7
Je peux penser à au moins une poignée d'humains qui réfuteraient votre thèse "vous ne pouvez pas créer un humain qui n'est ni masculin ni féminin", bien que ce soit toujours vrai de votre code ... mauvaise abstraction je suppose que je dis ? ;)
Frank W. Zammetti
2
Je pense qu'il est important de souligner que ce n'est que du polymorphisme car la version de goPee () à appeler ne peut être déterminée qu'au moment de l'exécution. Bien que cet exemple implique cela, il est agréable de souligner pourquoi c'est exactement le polymorphisme. De plus, il ne nécessite pas de cours frères. Il peut également s'agir d'une relation parent-enfant. Ou même des classes complètement indépendantes qui ont par hasard la même fonction. Un exemple de ceci peut être la fonction .toString (). Qui peut être appelé au hasard sur n'importe quel objet, mais le compilateur ne peut jamais savoir exactement quel type d'objet.
Tor Valamo
20
@AndrewDalke, +1 pour les notes sur la complexité biologique. En outre, goPeene prend pas un champ gravitationnel en entrée. Cette dépendance à l'égard de l'état global rend les tests unitaires CatheterizedIntersexAstronautdifficiles et montre que le sous-classement n'est pas toujours la meilleure méthode de composition des caractères.
Mike Samuel
99

Le polymorphisme est la capacité d'une instance de classe à se comporter comme si elle était une instance d'une autre classe dans son arbre d'héritage, le plus souvent l'une de ses classes ancêtres. Par exemple, en Java, toutes les classes héritent d'Object. Par conséquent, vous pouvez créer une variable de type Object et lui affecter une instance de n'importe quelle classe.

Une dérogationest un type de fonction qui se produit dans une classe qui hérite d'une autre classe. Une fonction de remplacement "remplace" une fonction héritée de la classe de base, mais le fait de telle manière qu'elle est 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 (). Étant donné que cette fonction est 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 Object, la version de toString qui se déclenchera réellement est celle définie sur Object lui-même. Cependant, comme la fonction est un remplacement, la définition de toString () de votre classe est utilisée même lorsque l'instance de classe '

La surcharge est l'action de définir plusieurs méthodes avec le même nom, mais avec des paramètres différents. Elle n'est pas liée à la neutralisation ni au polymorphisme.

Le Digital Gabeg
la source
8
C'est ancien mais le polymorphisme n'implique pas que l'autre classe doit être dans l'arbre d'héritage. C'est le cas en Java si vous considérez que les interfaces font partie de l'arborescence d'héritage, mais pas dans Go, où les interfaces sont implémentées implicitement.
JN
5
En fait, vous n'avez absolument pas besoin de classes pour le polymorphisme.
StCredZero
3
Je suis un débutant et corrigez-moi si je me trompe, mais je ne dirais pas que la surcharge n'est pas liée au polymorphisme. Au moins en Java, le polymorphisme est lorsque l'implémentation est choisie en fonction du type de l'appelant, et la surcharge est lorsque l'implémentation est choisie en fonction du type des paramètres, n'est-ce pas? Voir la similitude entre les deux m'aide à la comprendre.
csjacobs24
9
Incorrect. Ad hoc polymorphismest ce que vous avez décrit dans votre section Surcharge et est un cas de polymorphisme.
Jossie Calderon
1
"Il n'a aucun rapport avec le dépassement ou le polymorphisme". Cette affirmation est fausse.
Shailesh Pratapwar
45

Le polymorphisme signifie plus d'une forme, le même objet effectuant des opérations différentes selon l'exigence.

Le polymorphisme peut être atteint en utilisant deux façons, ce sont

  1. Remplacement de méthode
  2. Surcharge de méthode

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

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

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

Pour atteindre le polymorphisme, chaque développeur doit utiliser les mêmes noms de méthode dans le projet.

manoj
la source
4
+1 pour une belle réponse. La réponse acceptée n'explique qu'un type de polymorphisme. Cette réponse est complète.
apadana
1
le polymorphisme est un paradigme (POO), mais la surcharge et la surcharge sont des fonctionnalités linguistiques.
曾 其 威
Le polymorphisme peut également être obtenu par type générique.
Minh Nghĩa
43

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 d'une implémentation particulière de la méthode MakeNoise ().

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

Mark A. Nicolosi
la source
C'est un exemple de polymorphisme d'exécution. Le polymorphisme au moment de la compilation est également possible grâce à la surcharge de méthode et aux types génériques.
Pete Kirkham
Forme -> Parallélogramme -> Rectangle -> Carré
mpen
@ yankee2905 dans ce cas, je pense que vous pourriez utiliser des interfaces, car une classe pourrait implémenter plusieurs interfaces.
Sam003
1
@Zhisheng Ou ajouter une méthode pipi dans la classe parent abstraite? J'utiliserais l'interface pour implémenter autre chose.
joey rohan
42

La surcharge et la surcharge sont utilisées pour obtenir le polymorphisme.

Vous pouvez avoir une méthode dans une classe qui est remplacée dans une ou plusieurs sous-classes. La méthode fait des choses différentes 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 ou plusieurs ensembles d'arguments. La méthode fait différentes choses en fonction du ou des types d'arguments 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);
        }
    }
Patrick McElhaney
la source
Je suppose qu'il a été rejeté parce que la surcharge des méthodes n'est pas considérée historiquement comme faisant partie du polymorphisme dans le paradigme orienté objet. La surcharge de méthode et le polymorphisme sont deux caractéristiques orthogonales indépendantes d'un langage de programmation.
Sergio Acosta
7
Comme je l'ai dit dans ma réponse ici, je ne suis pas d'accord - les deux caractéristiques ne sont pas orthogonales, mais sont étroitement liées. Polymorphisme! = Héritage. Vous avez mon vote positif.
Peter Meyer
2
En d'autres termes, tapez polymorphisme vs polymorphisme ad hoc. Je vote pour cette réponse, même si elle n'est pas aussi complète qu'elle le devrait, car elle indique correctement que la surcharge et la surcharge sont liées au polymorphisme. Dire que le polymorphisme dans les langages OOP ne peut être atteint que par héritage de classe est tout simplement faux - nous devons nous rappeler qu'il existe d'autres langages OOP en plus de Java et C ++, où l'on peut utiliser des concepts tels que la répartition multiple, le polymorphisme ad hoc, le polymorphisme paramétrique, etc. .
rsenna
2
@rsenna Cela peut être incomplet mais cela répond à la question beaucoup mieux que les autres à mon humble avis. Aussi, très agréable que vous ayez mentionné le polymorphisme ad hoc et paramétrique.
Valentin Radu
15

Vous avez raison, la surcharge n'est pas la réponse.

Ni l'un ni l'autre ne l'emporte. Le dépassement est le moyen par lequel vous obtenez le polymorphisme. Le polymorphisme est la capacité d'un objet à varier le comportement en fonction de son type. Cela est mieux démontré lorsque l'appelant d'un objet qui présente un polymorphisme ne sait pas de quel type spécifique il s'agit.

Alex B
la source
3
Ce ne devrait pas être le comportement de l'objet qui change, mais sa mise en œuvre. Même comportement, implémentation différente, c'est du polymorphisme.
QBziZ
@QBziZ Vous devez définir le comportement , en particulier l'adjectif même . Si le comportement est le même, pourquoi leur mise en œuvre devrait-elle être différente? Ce n'est pas que quelqu'un soit mécontent d'une certaine implémentation, donc en requiert une autre.
Sнаđошƒаӽ
11

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

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

Le polymorphisme comprend également l'héritage et les méthodes de substitution, bien qu'ils puissent être abstraits ou virtuels dans le type de base. En termes de polymorphisme basé sur l'héritage, Java ne prend en charge que l'héritage de classe unique, ce qui limite son comportement polymorphe à celui d'une seule chaîne de types de base. Java prend en charge la mise en œuvre de plusieurs interfaces qui est encore une autre forme de comportement polymorphe.

Peter Meyer
la source
Vous avez raison en ce qui concerne la signification des mots en général, mais dans un contexte de programmation, lorsque les gens disent "polymorphisme", ils signifient toujours "polymorphisme basé sur l'héritage". Point intéressant, mais je pense que décrire le polymorphisme de cette façon va dérouter les gens.
Le Digital Gabeg
Il peut être plus facile d'expliquer le polymorphisme en termes d'héritage seul, mais la façon dont cette question particulière a été posée, je pense qu'il est prudent de décrire également le polymorphisme paramétrique.
Patrick McElhaney
4
Pour être clair, je pense que les différentes formes devraient être énoncées - ce que je n'ai même pas fait de manière adéquate - car il y a ici quelques réponses qui sont présentées comme absolues. Je ne suis respectueusement pas d'accord que dans "le contexte du programmeur ..." le polymorphisme "signifie toujours" le polymorphisme basé sur l'héritage ""
Peter Meyer
2
je pense que la surcharge est mieux classée comme Ad-hoc_polymorphism en.wikipedia.org/wiki/…
Manu
J'ai tendance à être d'accord avec «The Digital Gabeg» sur ce qui suit. Si vous discutez de POO, le polymorphisme signifie généralement le polymorphisme de sous-type, et si vous discutez de la théorie des types, cela signifie tout type de polymorphisme.
Manu
7

Le polymorphisme signifie simplement "plusieurs formes".

Il ne nécessite PAS d'héritage pour atteindre ... car l'implémentation d'interface, qui n'est pas du tout un héritage, répond à des besoins polymorphes. On peut soutenir que la mise en œuvre de l'interface répond à des besoins polymorphes «meilleurs» que l'héritage.

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

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

BillC
la source
2
Certainement la meilleure réponse à ce jour. Le polymorphisme peut être appliqué à toutes les constructions de langage, qu'il s'agisse de noms (classes) ou de verbes (méthodes).
Radu Gasler
6

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 y fassent leur implémentation respective.

Le code appelant n'a pas besoin de savoir de quel animal il s'agit.

C'est ce que je pense du polymorphisme.

Brian G
la source
4

Le polymorphisme est la capacité d'un objet à apparaître sous plusieurs formes. Cela implique d'utiliser l'héritage et les fonctions virtuelles pour construire une famille d'objets qui peuvent être échangés. La classe de base contient les prototypes des fonctions virtuelles, éventuellement non implémentées ou avec des implémentations par défaut selon l'application, et les différentes classes dérivées les implémentent chacune différemment pour affecter différents comportements.

mxg
la source
4

Ni:

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

Le dépassement est 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 exemple, les méthodes de la classe de base (parent) sont appelées mais pas avant que l'application ne sache quel est l'objet réel - il peut s'agir d'une classe enfant dont les méthodes sont différentes. En effet, n'importe quelle classe enfant peut être utilisée lorsqu'une classe de base est définie.

En Java, vous voyez beaucoup de polymorphisme avec 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 liste liée, un vecteur, un tableau ou une implémentation de liste personnalisée, tant qu'il agit 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.

jpeacock
la source
4

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

Pourquoi le polymorphisme est si important dans n'importe quel langage POO.

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

Supposons que vous êtes ingénieur logiciel dans une société de télévision et que vous soyez invité à é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 cela ait un code spécifique au contrôleur)
  2. get: - Pour obtenir la valeur d'un contrôleur (en supposant que cela ait un code spécifique au contrôleur)
  3. ajuster: - Pour valider l'entrée et paramétrer 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 invoquer 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;
        }

    }
    }
}

Vous avez maintenant notre première version d'application fonctionnelle prête à être déployée. Il est temps d'analyser le travail accompli jusqu'à présent.

Problèmes dans l'application TV version 1

  1. Le code de réglage (valeur int) est en double dans les trois classes. Vous souhaitez minimiser la duplicité du code. (Mais vous n'avez pas pensé à du code commun et à le déplacer dans une super classe pour éviter le code en double)

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

Après parfois, votre Boss revient vers vous et vous demande d'ajouter une fonctionnalité de réinitialisation à l'application existante. La réinitialisation mettrait 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 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 dans la version 2 de l'application TV

  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 augmente très haut, vous auriez des problèmes à conserver les références des contrôleurs.
  3. Le code de fonction de réinitialisation est étroitement associé au code de la classe de tous les contrôleurs (pour obtenir et définir les valeurs par défaut).
  4. La classe d'entités de réinitialisation (ResetFunctionV2) peut accéder à une autre méthode de la classe de contrôleur (ajuster), ce qui n'est pas souhaitable.

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

Maintenant, vous commencez à penser que cette nouvelle fonctionnalité à ajouter ressemble à la fonction de réinitialisation et les problèmes d'application (V2) seront multipliés si vous ne remodelez pas votre application.

Vous commencez à penser à utiliser l'héritage pour pouvoir profiter de la capacité polymorphe de JAVA et vous ajoutez une nouvelle classe abstraite (ControllerV3) à

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

Grâce à ces améliorations, vous disposez de la version 3 de votre application TV.

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 répertoriés dans la liste des problèmes de V2 aient été résolus, sauf

Problèmes dans la version 3 de l'application TV

  1. La classe d'entités de réinitialisation (ResetFunctionV3) peut accéder à une autre méthode de la classe de contrôleur (ajuster), ce qui n'est pas souhaitable.

Encore une fois, vous pensez à 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é vers de nouvelles fonctionnalités.

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

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

Et demandez à votre 1ère classe concrète de les implémenter 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, tout le problème auquel vous avez été confronté a été résolu et vous avez réalisé qu'avec l'utilisation de l'héritage et du polymorphisme, vous pouviez

  1. Gardez diverses parties de l'application librement couplées. (Les composants de la fonction de réinitialisation ou de mise à jour du pilote n'ont pas besoin d'être informés des classes de contrôleur 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 respectivement).
  2. L'amélioration de l'application devient plus facile (un nouvel ajout de contrôleur n'influe pas sur la réinitialisation ou la mise à jour du pilote, et il est désormais très facile pour vous d'en ajouter de nouveaux)
  3. Conserver la couche d'abstraction (maintenant, la fonction de réinitialisation ne peut voir que la méthode setDefault des contrôleurs et la fonction de réinitialisation ne peut voir que la méthode checkForDriverUpdate des contrôleurs).

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

Développeur
la source
3

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

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

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

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

Clyde
la source
2

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é à la surcharge mais pas vraiment à la surcharge.

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

Mat
la source
2

remplacer est plus comme 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. en d'autres termes, 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 d'implémentation.

Genjuro
la source
2

qu'est-ce que le polymorphisme?

De Java tutoriel

La définition par dictionnaire du polymorphisme fait référence à un principe de la biologie dans lequel un organisme ou une espèce peut avoir de nombreuses formes ou stades différents. Ce principe peut également être appliqué à la programmation orientée objet et aux langages comme 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, la réponse prioritaire devrait être acceptée.

Concernant votre deuxième requête:

SI vous aviez une classe de base abstraite qui définissait une méthode sans implémentation et que vous définissiez cette méthode dans la sous-classe, est-ce toujours une surcharge?

Cela devrait être appelé prioritaire.

Jetez un œil à cet exemple pour comprendre les différents types de substitution.

  1. La classe de base ne fournit aucune implémentation et la sous-classe doit remplacer la méthode complète - (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 remplacera 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();
        }       
    }
}

production:

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:
Ravindra babu
la source
2

Je pense que vous mélangez des concepts. Le polymorphisme est la capacité d'un objet à se comporter différemment au moment de l'exécution. Pour y parvenir, vous avez besoin de deux conditions:

  1. Reliure tardive
  2. Héritage.

Cela dit, la surcharge signifie quelque chose de différent à remplacer selon la langue que vous utilisez. Par exemple, en Java, il n'existe pas de surcharge mais de surcharge . Les méthodes surchargées avec une signature différente de sa classe de base sont disponibles dans la sous-classe. Sinon, ils seraient remplacés (veuillez voir que je veux dire maintenant qu'il n'y a aucun moyen d'appeler votre méthode de classe de base depuis l'extérieur de l'objet).

Cependant, en C ++, ce n'est pas le cas. Toute méthode surchargée , indépendamment du fait que la signature soit la même ou non (quantité différente, type différent) 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 de la sous-classe, évidemment.

Donc, la réponse est quand on parle de surcharge d' utilisation de Java . Dans tout autre langage peut être différent comme cela arrive en c ++

user1154840
la source
1

Le polymorphisme est plus probable dans la mesure où il signifie ... à OVERRIDING en java

Il s'agit du comportement différent 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 java PURE ...

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

Rajan
la source
1

Le polymorphisme est une implémentation multiple d'un objet ou vous pourriez dire plusieurs formes d'un objet. disons que vous avez une classe Animalscomme classe de base abstraite et qu'elle a 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 ainsi certains d'entre eux avec 2 pattes, d'autres avec 4 et certains sans pattes, etc. Pour définir différents movement()de chaque animal sur terre, nous devons appliquer le polymorphisme. Cependant, vous devez définir plus de classes, c'est- à- dire la classe pour y parvenir. Le mot-clé ici est prioritaire, la surcharge est différente et n'est pas considérée comme du polymorphisme. en cas de surcharge, vous pouvez définir plusieurs méthodes "du même nom" mais avec des paramètres différents sur le même objet ou la même classe.Dogs Cats Fish etc. Ensuite, vous devez étendre ces classes à partir de la classe de base Animalset remplacer sa méthodemovement() avec une nouvelle fonctionnalité de mouvement basée sur chaque animal que vous avez. Vous pouvez aussi utiliserInterfaces

SolidSnake
la source
0

Le polymorphisme concerne la capacité d'un langage à avoir un objet différent traité de manière uniforme en utilisant une seule interface; en tant que tel, il est lié à la substitution, de sorte que l'interface (ou la classe de base) est polymorphe, l'implémenteur est l'objet qui remplace (deux faces de la même médaille)

de toute façon, la différence entre les deux termes est mieux expliquée en utilisant d'autres langages, tels que c ++: un objet polymorphe en c ++ se comporte comme l'équivalent 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 vrai type 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; permettez-moi de faire 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é aussi découpage d'objets).

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

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

dans les deux cas, il n'imprimera que woff .. puisque a et b font référence à un chien de classe

Lorenzo Boccaccia
la source
animal a = nouveau chien (); a a été construit comme un chien et imprimera "woff". Si vous voulez qu'il imprime le bruit, alors vous devez le transposer. ((Animal) a) .makeRumor ()
Chris Cudmore
C'est une référence à l'upcasting, mais l'objet est toujours un chien. Si vous voulez que ce soit un animal, vous devez explicitement transposer l'objet.
Chris Cudmore
Deviner. La question a été marquée Java. Vous avez répondu C ++. Vous avez peut-être raison en C ++. J'ai tout à fait raison en Java.
Chris Cudmore
devrait se produire chaque fois qu'un constructeur de copie est impliqué ici est une référence fredosaurus.com/notes-cpp/oop-condestructors/… cas trois correspondances; ignorer le nouvel opérateur qui n'est là que pour lever l'ambiguïté de la création.
Lorenzo Boccaccia
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());

    }
}
bharanitharan
la source