Question

En termes de Java, lorsque quelqu'un demande:

  

qu'est-ce que le polymorphisme?

Une surcharge ou une neutralisation constitueraient-elles une réponse acceptable?

Je pense qu’il ya 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, est-ce que cette méthode est toujours surchargée?

Je pense que la surcharge n'est pas la bonne réponse pour vous.

Était-ce utile?

La solution

Le moyen le plus clair d’exprimer le polymorphisme consiste à utiliser 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 () n'est pas définissable pour Humans. Il n'est définissable que pour les sous-classes Male et Female. De plus, l’homme est un concept abstrait & # 8212; Vous ne pouvez pas créer un humain qui n'est 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();
}

Cela vous donnerait:

Stand Up
Sit Down
...

Autres conseils

Le

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, en 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 toute classe.

Un remplacement 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. Cependant, 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 caché derrière un polymorphisme.

La surcharge consiste à définir plusieurs méthodes portant le même nom, mais avec des paramètres différents. Cela n’a aucun rapport avec le suprématie ni le polymorphisme.

Voici un exemple de polymorphisme dans 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 poing. Drôle nous avons utilisé le même exemple. Mais le code ci-dessus devrait aider à clarifier les concepts.

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

Le polymorphisme peut être obtenu en utilisant deux méthodes:

  1. Méthode surchargée
  2. surcharge de méthode

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

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 la classe parent est utilisée dans la classe enfant.

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

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 remplacé dans un ou     plus de sous-classes. La méthode fait     choses différentes selon lequel     la classe a été 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 pourriez aussi avoir une méthode qui est      surchargé avec deux jeux d'arguments ou plus. La méthode fait     différentes choses en fonction de la     type (s) 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);
        }
    }

Vous avez raison de dire que la surcharge n'est pas la solution.

Ni est prioritaire. 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 l'objet.

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ètres différents. Un bon exemple est la surcharge de l'opérateur. Vous pouvez définir " + " 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, ce qui limite son comportement polymorphique à 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.

Polymorphisme signifie simplement "Plusieurs formes".

L'héritage n'est pas OBLIGATOIRE pour pouvoir ... car l'implémentation d'interface, qui n'est pas du tout l'héritage, répond aux besoins polymorphes. On peut soutenir que la mise en œuvre 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 feriez mieux de 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.

L'exemple classique, les chiens et les chats sont des animaux, les animaux utilisent la méthode makeNoise. Je peux parcourir une série d'animaux appelant makeNoise et m'attendre à ce qu'ils fassent leur implémentation respective.

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

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

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 avec les implémentations par défaut comme l’indique l’application, et les différentes classes dérivées les implémentent différemment pour affecter différents comportements.

Ni l'un ni l'autre:

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

Le remplacement survient lorsqu'une classe enfant remplace la méthode d'un parent par l'une de ses propres méthodes (elle-même ne constitue pas 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 connaisse la nature de 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.

En Java, le polymorphisme est très répandu dans la bibliothèque de collections:

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

La liste 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 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 () seraient choisis par le compilateur pour correspondre aux paramètres.

Le terme surcharge désigne le fait d'avoir plusieurs versions du 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) { ... }

Ces fonctions peuvent donc 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

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

La substitution est le lieu 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 réponse simple: "Remplacer". pour la question "Qu'est-ce qu'un polymorphisme?" Je demanderais des explications supplémentaires.

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. En d'autres termes, la décision de choisir la méthode de niveau à appeler sera prise au moment de l'exécution, pas au moment de la compilation. cela conduit au concept d'interface et de mise en œuvre.

  

qu'est-ce que le polymorphisme?

De java didacticiel

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 tout en partageant les mêmes fonctionnalités que la classe parente.

Compte tenu des exemples et de la définition, la réponse outre devrait être acceptée.

En ce qui concerne votre deuxième 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?

Cela devrait être appelé neutralisation.

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

  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 l'implémentation par défaut et la sous-classe peut changer le comportement
  3. La sous-classe ajoute une extension à la mise en oeuvre de la classe de base en appelant super.methodName () en tant que 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();
        }       
    }
}

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:

Je pense que vous mélangez les concepts. Le 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 essentiels:

  1. Liaison tardive
  2. Héritage.

Cela dit, surcharger signifie autre chose que écraser en fonction de la langue que vous utilisez. Par exemple, en Java, il n’existe pas de remplacement mais de une surcharge . Des méthodes surchargées avec une signature différente de celle de la classe de base sont disponibles dans la sous-classe. Sinon, ils seraient remplacé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. Toute méthode surchargée , que la signature soit identique 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, bien entendu.

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

Although, Polymorphism is already explained in great details in this post but I would like put more emphasis on why part of it.

Why Polymorphism is so important in any OOP language.

Let’s try to build a simple application for a TV with and without Inheritance/Polymorphism. Post each version of the application, we do a small retrospective.

Supposing, you are a software engineer at a TV company and you are asked to write software for Volume, Brightness and Colour controllers to increase and decrease their values on user command.

You start with writing classes for each of these features by adding

  1. set:- To set a value of a controller.(Supposing this has controller specific code)
  2. get:- To get a value of a controller.(Supposing this has controller specific code)
  3. adjust:- To validate the input and setting a controller.(Generic validations.. independent of controllers)
  4. user input mapping with controllers :- To get user input and invoking controllers accordingly.

Application Version 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;
        }

    }
    }
}

Now you have our first version of working application ready to be deployed. Time to analyze the work done so far.

Issues in TV Application Version 1

  1. Adjust(int value) code is duplicate in all three classes. You would like to minimize the code duplicity. (But you did not think of common code and moving it to some super class to avoid duplicate code)

You decide to live with that as long as your application works as expected.

After sometimes, your Boss comes back to you and asks you to add reset functionality to the existing application. Reset would set all 3 three controller to their respective default values.

You start writing a new class (ResetFunctionV2) for the new functionality and map the user input mapping code for this new feature.

Application Version 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;
            }

        }
    }
}

So you have your application ready with Reset feature. But, now you start realizing that

Issues in TV Application Version 2

  1. If a new controller is introduced to the product, you have to change Reset feature code.
  2. If the count of the controller grows very high, you would have issue in holding the references of the controllers.
  3. Reset feature code is tightly coupled with all the controllers Class’s code(to get and set default values).
  4. Reset feature class (ResetFunctionV2) can access other method of the Controller class’s (adjust) which is undesirable.

At the same time, You hear from you Boss that you might have to add a feature wherein each of controllers, on start-up, needs to check for the latest version of driver from company’s hosted driver repository via internet.

Now you start thinking that this new feature to be added resembles with Reset feature and Issues of Application (V2) will be multiplied if you don’t re-factor your application.

You start thinking of using inheritance so that you can take advantage from polymorphic ability of JAVA and you add a new abstract class (ControllerV3) to

  1. Declare the signature of get and set method.
  2. Contain adjust method implementation which was earlier replicated among all the controllers.
  3. Declare setDefault method so that reset feature can be easily implemented leveraging Polymorphism.

With these improvements, you have version 3 of your TV application ready with you.

Application Version 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;
            }

        }
    }
}

Although most of the Issue listed in issue list of V2 were addressed except

Issues in TV Application Version 3

  1. Reset feature class (ResetFunctionV3) can access other method of the Controller class’s (adjust) which is undesirable.

Again, you think of solving this problem, as now you have another feature (driver update at startup) to implement as well. If you don’t fix it, it will get replicated to new features as well.

So you divide the contract defined in abstract class and write 2 interfaces for

  1. Reset feature.
  2. Driver Update.

And have your 1st concrete class implement them as below

Application Version 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;
            }

        }
    }
}

Now all of the issue faced by you got addressed and you realized that with the use of Inheritance and Polymorphism you could

  1. Keep various part of application loosely coupled.( Reset or Driver Update feature components don’t need to be made aware of actual controller classes(Volume, Brightness and Colour), any class implementing OnReset or OnStart will be acceptable to Reset or Driver Update feature components respectively).
  2. Application enhancement becomes easier.(New addition of controller wont impact reset or driver update feature component, and it is now really easy for you to add new ones)
  3. Keep layer of abstraction.(Now Reset feature can see only setDefault method of controllers and Reset feature can see only checkForDriverUpdate method of controllers)

Hope, this helps :-)

Polymorphism is more likely as far as it's meaning is concerned ... to OVERRIDING in java

It's all about different behavior of the SAME object in different situations(In programming way ... you can call different ARGUMENTS)

I think the example below will help you to understand ... Though it's not PURE java code ...

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

But if we change the ARGUMENT ... the BEHAVIOR will be changed ...

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

The Person(here the "Object") is same ...

Polymorphism is a multiple implementations of an object or you could say multiple forms of an object. lets say you have class Animals as the abstract base class and it has a method called movement() which defines the way that the animal moves. Now in reality we have different kinds of animals and they move differently as well some of them with 2 legs, others with 4 and some with no legs, etc.. To define different movement() of each animal on earth, we need to apply polymorphism. However, you need to define more classes i.e. class Dogs Cats Fish etc. Then you need to extend those classes from the base class Animals and override its method movement() with a new movement functionality based on each animal you have. You can also use Interfaces to achieve that. The keyword in here is overriding, overloading is different and is not considered as polymorphism. with overloading you can define multiple methods "with same name" but with different parameters on same object or class.

Polymorphism relates to the ability of a language to have different object treated uniformly by using a single interfaces; as such it is related to overriding, so the interface (or the base class) is polymorphic, the implementor is the object which overrides (two faces of the same medal)

anyway, the difference between the two terms is better explained using other languages, such as c++: a polymorphic object in c++ behaves as the java counterpart if the base function is virtual, but if the method is not virtual the code jump is resolved statically, and the true type not checked at runtime so, polymorphism include the ability for an object to behave differently depending on the interface used to access it; let me make an example in 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

(supposing that makeRumor is NOT virtual)

java doesn't truly offer this level of polymorphism (called also object slicing).

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

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

on both case it will only print woff.. since a and b is refering to class dog

import java.io.IOException;

class Super {

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

}

class SubOne extends Super {

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

}

class SubTwo extends Super {

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

}

class SubThree extends Super {

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

}

class SubFour extends Super {

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

}

class SubFive extends Super {

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

}

class SubSix extends Super {

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

}

class SubSeven extends Super {

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

}

public class Test{

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

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

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

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

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

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

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

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

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

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

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

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

    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top