Polymorphismus vs Überschreiben vs Überladen


347

In Bezug auf Java, wenn jemand fragt:

Was ist Polymorphismus?

Wäre Überladen oder Überschreiben eine akzeptable Antwort?

Ich denke, da steckt noch ein bisschen mehr dahinter.

Wenn Sie eine abstrakte Basisklasse hatten, die eine Methode ohne Implementierung definiert hat, und diese Methode in der Unterklasse definiert haben, ist das immer noch überschreibend?

Ich denke, Überladung ist nicht die richtige Antwort.


Die folgenden Antworten erklären sehr gut den Polymorphismus. Aber ich habe starke Einwände zu sagen, dass Überladung eine Art von Polymorphismus ist, die ich in meiner Frage und Antwort zu rechtfertigen versuchte, die sich tatsächlich auf Überladung konzentriert, ist Polymorphismus oder nicht. Ich habe versucht, die Antwort von @The Digital Gabeg in diesem Thread zu rechtfertigen. Siehe Ausarbeitung: Das Überladen von Methoden ist eine statische Bindung / Bindung zur Kompilierungszeit, jedoch kein Polymorphismus. Ist es richtig, statische Bindung mit Polymorphismus zu korrelieren?
PraveenKumar Lalasangi

Antworten:


894

Der klarste Weg, Polymorphismus auszudrücken, ist über eine abstrakte Basisklasse (oder Schnittstelle).

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

Diese Klasse ist abstrakt, weil die goPee() Methode für Menschen nicht definierbar ist. Es ist nur für die Unterklassen Männlich und Weiblich definierbar. Mensch ist auch ein abstraktes Konzept - Sie können keinen Menschen erschaffen, der weder männlich noch weiblich ist. Es muss der eine oder andere sein.

Daher verschieben wir die Implementierung mithilfe der abstrakten Klasse.

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

und

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

Jetzt können wir einem ganzen Raum voller Menschen sagen, dass sie pinkeln sollen.

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

Wenn Sie dies ausführen, erhalten Sie:

Stand Up
Sit Down
...

37
@ Yuudachi. Ich habe mir dieses Beispiel ausgedacht, als ich eine Klasse unterrichtete. Die kanonische Klasse "Bank Account" drückte die "Abstraktheit" der Basisklasse nicht wirklich aus. Das andere kanonische Beispiel (Tier, Lärm machen) war zu abstrakt zum Verstehen. Ich suchte nach einer einzigen Basis mit zu offensichtlichen Unterklassen. Eigentlich war goPee () das einzige Beispiel, das ich mir ausgedacht habe und das weder sexistisch noch stereotyp war. (Obwohl ich im Unterricht "links im Flur" gedruckt habe, anstatt aufzustehen oder mich hinzusetzen.)
Chris Cudmore

100
Dieses Beispiel zeigt auch deutlich, wie schwierig es ist, ein hierarchisches System zur Beschreibung biologischer Systeme zu verwenden. Einige Menschen, wie die sehr jungen, pinkeln in fast jeder Position - und Babys können nicht einfach angewiesen werden, goPee () zu machen. Einige Menschen sind intersexuell, wobei die biologischen Bezeichnungen "männlich" oder "weiblich" ziemlich schlecht definiert werden; Die sozialen Bedeutungen sind noch komplexer. Als Lehrbeispiel zeigt es, wie Modellierungsannahmen negative Ergebnisse haben können, beispielsweise die Implikation, dass jemand (z. B. ein Student der OO-Programmierung), der inkontinent oder intersexuell ist, nicht wirklich menschlich ist.
Andrew Dalke

7
Ich kann mir zumindest eine Handvoll Menschen vorstellen, die Ihre These "Sie können keinen Menschen erschaffen, der weder männlich noch weiblich ist" widerlegen würden, obwohl dies für Ihren Code immer noch zutreffen würde ... schlechte Abstraktion, nehme ich an ? ;)
Frank W. Zammetti

2
Ich denke, es ist wichtig darauf hinzuweisen, dass es nur Polymorphismus ist, da die aufzurufende Version von goPee () nur zur Laufzeit bestimmt werden kann. Während dieses Beispiel dies impliziert, ist es schön darauf hinzuweisen, warum genau das Polymorphismus ist. Außerdem sind keine Geschwisterklassen erforderlich. Es kann auch eine Eltern-Kind-Beziehung sein. Oder sogar völlig unabhängige Klassen, die zufällig die gleiche Funktion haben. Ein Beispiel hierfür kann die Funktion .toString () sein. Was für jedes Objekt zufällig aufgerufen werden kann, aber der Compiler kann nie genau wissen, welcher Objekttyp.
Tor Valamo

20
@ AndrewDalke, +1 für Hinweise zur biologischen Komplexität. Nimmt goPeeauch kein Gravitationsfeld als Eingabe. Diese Abhängigkeit vom globalen Zustand erschwert das Testen von Einheiten CatheterizedIntersexAstronautund zeigt, dass Unterklassen möglicherweise nicht immer die beste Methode für die Zusammensetzung von Merkmalen sind.
Mike Samuel

99

Polymorphismus ist die Fähigkeit einer Klasseninstanz, sich so zu verhalten, als wäre sie eine Instanz einer anderen Klasse in ihrem Vererbungsbaum, meistens einer ihrer Vorfahrenklassen. In Java erben beispielsweise alle Klassen von Object. Daher können Sie eine Variable vom Typ Object erstellen und ihr eine Instanz einer beliebigen Klasse zuweisen.

Ein Overrideist eine Art von Funktion, die in einer Klasse auftritt, die von einer anderen Klasse erbt. Eine Überschreibungsfunktion "ersetzt" eine von der Basisklasse geerbte Funktion, tut dies jedoch so, dass sie auch dann aufgerufen wird, wenn eine Instanz ihrer Klasse durch Polymorphismus vorgibt, ein anderer Typ zu sein. Mit Bezug auf das vorherige Beispiel können Sie Ihre eigene Klasse definieren und die Funktion toString () überschreiben. Da diese Funktion von Object geerbt wird, ist sie weiterhin verfügbar, wenn Sie eine Instanz dieser Klasse in eine Variable vom Typ Objekt kopieren. Wenn Sie toString () für Ihre Klasse aufrufen, während sie vorgibt, ein Objekt zu sein, ist normalerweise die Version von toString, die tatsächlich ausgelöst wird, die für Object selbst definierte. Da es sich bei der Funktion jedoch um eine Überschreibung handelt, wird die Definition von toString () aus Ihrer Klasse auch dann verwendet, wenn die Klasseninstanz '

Beim Überladen werden mehrere Methoden mit demselben Namen, aber unterschiedlichen Parametern definiert. Es hat nichts mit Überschreiben oder Polymorphismus zu tun.


8
Dies ist alt, aber Polymorphismus bedeutet nicht, dass sich die andere Klasse im Vererbungsbaum befinden muss. Dies geschieht in Java, wenn Sie Schnittstellen als Teil des Vererbungsbaums betrachten, nicht jedoch in Go, wo Schnittstellen implizit implementiert sind.
JN

5
Eigentlich brauchen Sie überhaupt keine Klassen für Polymorphismus.
StCredZero

3
Ich bin ein Neuling und korrigiere mich, wenn ich falsch liege, aber ich würde nicht sagen, dass Überladung nichts mit Polymorphismus zu tun hat. Zumindest in Java ist Polymorphismus, wenn die Implementierung basierend auf dem Typ des Aufrufers ausgewählt wird, und Überladung ist, wenn die Implementierung basierend auf dem Typ der Parameter ausgewählt wird, nicht wahr? Die Ähnlichkeit zwischen den beiden zu sehen, hilft mir, sie zu verstehen.
csjacobs24

9
Falsch. Ad hoc polymorphismist das, was Sie in Ihrem Abschnitt Überladen beschrieben haben, und es handelt sich um Polymorphismus.
Jossie Calderon

1
"Es hat nichts mit Überschreiben oder Polymorphismus zu tun". Diese Aussage ist falsch.
Shailesh Pratapwar

45

Polymorphismus bedeutet mehr als eine Form, wobei dasselbe Objekt je nach Anforderung unterschiedliche Operationen ausführt.

Polymorphismus kann auf zwei Arten erreicht werden:

  1. Methode überschreiben
  2. Methodenüberladung

Methodenüberladung bedeutet, dass zwei oder mehr Methoden in derselben Klasse unter Verwendung desselben Methodennamens geschrieben werden, die Übergabeparameter jedoch unterschiedlich sind.

Das Überschreiben von Methoden bedeutet, dass wir die Methodennamen in den verschiedenen Klassen verwenden. Dies bedeutet, dass die Methode der übergeordneten Klasse in der untergeordneten Klasse verwendet wird.

In Java kann eine Superklassenreferenzvariable das Unterklassenobjekt enthalten, um Polymorphismus zu erzielen.

Um den Polymorphismus zu erreichen, muss jeder Entwickler im Projekt dieselben Methodennamen verwenden.


4
+1 für eine nette Antwort. Die akzeptierte Antwort erklärt nur eine Art von Polymorphismus. Diese Antwort ist vollständig.
Apadana

1
Polymorphismus ist ein Paradigma (OOP), aber Überschreiben und Überladen sind Sprachfunktionen.
其 威

Polymorphismus kann auch durch generischen Typ erreicht werden.
Minh Nghĩa

43

Hier ist ein Beispiel für Polymorphismus in 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 ());
}

Die Hauptfunktion kennt den Typ des Tieres nicht und hängt vom Verhalten einer bestimmten Implementierung der MakeNoise () -Methode ab.

Edit: Sieht so aus, als hätte Brian mich bis zum Anschlag geschlagen. Komisch, dass wir das gleiche Beispiel verwendet haben. Der obige Code soll jedoch zur Verdeutlichung der Konzepte beitragen.


Es ist ein Beispiel für Laufzeitpolymorphismus. Der Polymorphismus der Kompilierungszeit ist auch durch Methodenüberladung und generische Typen möglich.
Pete Kirkham

Form -> Parallelogramm -> Rechteck -> Quadrat
mpen

@ yankee2905 In diesem Fall könnten Sie Schnittstellen verwenden, da eine Klasse mehrere Schnittstellen implementieren könnte.
Sam003

1
@Zhisheng Oder eine Pee-Methode in der abstrakten Elternklasse hinzufügen? Ich würde die Schnittstelle verwenden, um etwas anderes zu implementieren.
Joey Rohan

42

Sowohl Überschreiben als auch Überladen werden verwendet, um Polymorphismus zu erreichen.

Sie könnten eine Methode in einer Klasse haben, die in einer oder mehreren Unterklassen überschrieben wird . Die Methode führt verschiedene Aktionen aus, je nachdem, welche Klasse zum Instanziieren eines Objekts verwendet wurde.

    abstract class Beverage {
       boolean isAcceptableTemperature();
    }

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

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

Sie könnten auch eine Methode haben, die mit zwei oder mehr Argumenten überladen ist . Die Methode führt verschiedene Aktionen aus, die auf den übergebenen Argumenttypen basieren.

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

Ich nehme an, es wurde abgelehnt, weil historisch gesehen das Überladen von Methoden im objektorientierten Paradigma nicht als Teil des Polymorphismus betrachtet wird. Methodenüberladung und Polymorphismus sind zwei ortogonale, unabhängige Merkmale einer Programmiersprache.
Sergio Acosta

7
Wie ich in meiner Antwort hier angegeben habe, bin ich anderer Meinung - die beiden Merkmale sind nicht orthogonal, sondern eng miteinander verbunden. Polymorphismus! = Vererbung. Du hast meine Stimme.
Peter Meyer

2
Mit anderen Worten, Typpolymorphismus vs. Ad-hoc-Polymorphismus. Ich stimme dieser Antwort zu, auch wenn sie nicht so vollständig ist, wie sie sollte, weil sie korrekt besagt, dass sowohl Überladung als auch Überschreiben mit Polymorphismus zusammenhängen. Zu sagen, dass Polymorphismus in OOP-Sprachen nur durch Klassenvererbung erreicht werden kann, ist einfach falsch - wir sollten uns daran erinnern, dass es neben Java und C ++ noch einige andere OOP-Sprachen gibt, in denen Konzepte wie Mehrfachversand, Ad-hoc-Polymorphismus, parametrischer Polymorphismus usw. verwendet werden können .
Rsenna

2
@rsenna Dies mag unvollständig sein, aber es beantwortet die Frage viel besser als der Rest meiner Meinung nach. Sehr schön, dass Sie den ad-hoc und parametrischen Polymorphismus erwähnt haben.
Valentin Radu

15

Sie haben Recht, dass Überladung nicht die Antwort ist.

Weder ist übergeordnet. Überschreiben ist das Mittel, mit dem Sie Polymorphismus erhalten. Polymorphismus ist die Fähigkeit eines Objekts, das Verhalten je nach Typ zu variieren. Dies lässt sich am besten demonstrieren, wenn der Aufrufer eines Objekts, das Polymorphismus aufweist, nicht weiß, um welchen spezifischen Typ es sich bei dem Objekt handelt.


3
Es sollte sich nicht das Verhalten des Objekts ändern, sondern seine Implementierung. Gleiches Verhalten, unterschiedliche Implementierung, das ist Polymorphismus.
QBziZ

@QBziZ Sie müssen das Verhalten definieren , insbesondere das gleiche Adjektiv . Wenn das Verhalten gleich ist, warum sollte ihre Implementierung unterschiedlich sein? Es ist nicht so, dass jemand mit einer bestimmten Implementierung unzufrieden ist, daher ist eine andere erforderlich.
Sнаđошƒаӽ

11

Insbesondere wenn Sie sagen, dass Überladen oder Überschreiben nicht das vollständige Bild ergibt. Polymorphismus ist einfach die Fähigkeit eines Objekts, sein Verhalten basierend auf seinem Typ zu spezialisieren.

Ich würde einigen der Antworten hier nicht zustimmen, da Überladung eine Form des Polymorphismus (parametrischer Polymorphismus) ist, falls sich eine Methode mit demselben Namen unterschiedlich verhalten kann und unterschiedliche Parametertypen ergibt. Ein gutes Beispiel ist die Überlastung des Bedieners. Sie können "+" definieren, um verschiedene Arten von Parametern zu akzeptieren - beispielsweise Zeichenfolgen oder Ints - und basierend auf diesen Typen verhält sich "+" unterschiedlich.

Polymorphismus umfasst auch Vererbungs- und überschreibende Methoden, obwohl sie im Basistyp abstrakt oder virtuell sein können. In Bezug auf den vererbungsbasierten Polymorphismus unterstützt Java nur die Vererbung einzelner Klassen, wodurch das polymorphe Verhalten auf das einer einzelnen Kette von Basistypen beschränkt wird. Java unterstützt die Implementierung mehrerer Schnittstellen, was eine weitere Form des polymorphen Verhaltens darstellt.


Sie haben Recht damit, was die beteiligten Wörter im Allgemeinen bedeuten, aber in einem Programmierkontext bedeuten Menschen, die "Polymorphismus" sagen, immer "vererbungsbasierten Polymorphismus". Interessanter Punkt, aber ich denke, dass die Beschreibung des Polymorphismus auf diese Weise die Menschen verwirren wird.
The Digital Gabeg

Es mag einfacher sein, Polymorphismus allein anhand der Vererbung zu erklären, aber die Art und Weise, wie diese spezielle Frage gestellt wurde, halte ich es für ratsam, auch parametrischen Polymorphismus zu beschreiben.
Patrick McElhaney

4
Um es klar auszudrücken, ich denke, die verschiedenen Formen sollten angegeben werden - was ich noch nicht einmal ausreichend getan habe -, da es hier einige Antworten gibt, die als absolut dargestellt werden. Ich bin mit Respekt anderer Meinung, dass im "Programmiererkontext ..." Polymorphismus "immer" vererbungsbasierter Polymorphismus "bedeutet"
Peter Meyer

2
Ich denke, Überladung ist besser als Ad-hoc_polymorphism kategorisiert en.wikipedia.org/wiki/…
Manu

Ich stimme 'The Digital Gabeg' in folgenden Punkten eher zu. Wenn Sie über OOP sprechen, bedeutet Polymorphismus normalerweise Subtyp-Polymorphismus, und wenn Sie über Typentheorie sprechen, bedeutet dies jede Art von Polymorphismus.
Manu

7

Polymorphismus bedeutet einfach "viele Formen".

Es ist keine Vererbung erforderlich, um ... zu erreichen, da die Schnittstellenimplementierung, die überhaupt keine Vererbung ist, polymorphen Anforderungen dient. Die Schnittstellenimplementierung dient wohl den polymorphen Anforderungen "besser" als die Vererbung.

Würden Sie zum Beispiel eine Superklasse erstellen, um alle Dinge zu beschreiben, die fliegen können? Ich sollte nicht denken. Am besten erstellen Sie eine Schnittstelle, die den Flug beschreibt, und lassen sie dabei.

Da Schnittstellen das Verhalten beschreiben und Methodennamen das Verhalten (für den Programmierer) beschreiben, ist es nicht allzu weit entfernt, die Überladung von Methoden als eine geringere Form des Polymorphismus zu betrachten.


2
Auf jeden Fall die bisher beste Antwort. Polymorphismus kann auf alle Sprachkonstrukte angewendet werden, sei es Substantive (Klassen) oder Verben (Methoden).
Radu Gasler

6

Das klassische Beispiel: Hunde und Katzen sind Tiere, Tiere haben die Methode makeNoise. Ich kann eine Reihe von Tieren durchlaufen, die makeNoise für sie aufrufen, und erwarten, dass sie dort die entsprechende Implementierung durchführen.

Der Rufcode muss nicht wissen, um welches Tier es sich handelt.

Das ist, was ich als Polymorphismus betrachte.


4

Polymorphismus ist die Fähigkeit eines Objekts, in mehreren Formen zu erscheinen. Dies beinhaltet die Verwendung von Vererbung und virtuellen Funktionen, um eine Familie von Objekten zu erstellen, die ausgetauscht werden können. Die Basisklasse enthält die Prototypen der virtuellen Funktionen, möglicherweise nicht implementiert oder mit Standardimplementierungen, wie es die Anwendung vorschreibt, und die verschiedenen abgeleiteten Klassen implementieren sie jeweils unterschiedlich, um unterschiedliche Verhaltensweisen zu beeinflussen.


4

Weder:

Überladen ist, wenn Sie denselben Funktionsnamen haben, der unterschiedliche Parameter akzeptiert.

Überschreiben ist, wenn eine untergeordnete Klasse die Methode eines Elternteils durch eine eigene ersetzt (dies stellt an sich keinen Polymorphismus dar).

Polymorphismus ist eine späte Bindung, z. B. werden die Basisklassenmethoden (übergeordnete Methoden) aufgerufen, aber erst zur Laufzeit weiß die Anwendung, was das eigentliche Objekt ist - es kann sich um eine untergeordnete Klasse handeln, deren Methoden unterschiedlich sind. Dies liegt daran, dass jede untergeordnete Klasse verwendet werden kann, in der eine Basisklasse definiert ist.

In Java sehen Sie viel Polymorphismus in der Sammlungsbibliothek:

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

List ist die Basisklasse. Der Compiler hat keine Ahnung, ob Sie eine verknüpfte Liste, einen Vektor, ein Array oder eine benutzerdefinierte Listenimplementierung zählen, solange sie sich wie eine Liste verhält:

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

Wenn Sie überladen wären, hätten Sie:

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

und die richtige Version von countStuff () wird vom Compiler ausgewählt, um den Parametern zu entsprechen.


4

Obwohl Polymorphismus in diesem Beitrag bereits ausführlich erklärt wird, möchte ich mehr Wert darauf legen, warum ein Teil davon ist.

Warum Polymorphismus in jeder OOP-Sprache so wichtig ist.

Versuchen wir, eine einfache Anwendung für einen Fernseher mit und ohne Vererbung / Polymorphismus zu erstellen. Veröffentlichen Sie jede Version der Anwendung, wir machen eine kleine Retrospektive.

Angenommen, Sie sind Softwareentwickler bei einem Fernsehunternehmen und werden gebeten, Software für Lautstärkeregler, Helligkeitsregler und Farbregler zu schreiben, um deren Werte auf Benutzerbefehl zu erhöhen und zu verringern.

Sie beginnen mit dem Schreiben von Klassen für jede dieser Funktionen, indem Sie hinzufügen

  1. set: - Zum Festlegen eines Werts eines Controllers. (Angenommen, dieser hat einen controller-spezifischen Code.)
  2. get: - Um einen Wert eines Controllers zu erhalten. (Angenommen, dieser hat einen Controller-spezifischen Code.)
  3. anpassen: - Um die Eingabe zu validieren und einen Controller einzustellen. (Allgemeine Validierungen .. unabhängig von Controllern)
  4. Benutzereingabezuordnung mit Controllern: - Um Benutzereingaben zu erhalten und Controller entsprechend aufzurufen.

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

    }
    }
}

Jetzt können Sie unsere erste Version der Arbeitsanwendung bereitstellen. Zeit, die bisher geleistete Arbeit zu analysieren.

Probleme in der TV-Anwendung Version 1

  1. Der Anpassungscode (int value) ist in allen drei Klassen doppelt vorhanden. Sie möchten die Codeduplizität minimieren. (Aber Sie haben nicht an allgemeinen Code gedacht und ihn in eine Superklasse verschoben, um doppelten Code zu vermeiden.)

Sie entscheiden sich, damit zu leben, solange Ihre Anwendung wie erwartet funktioniert.

Manchmal kommt Ihr Chef zu Ihnen zurück und fordert Sie auf, der vorhandenen Anwendung Reset-Funktionen hinzuzufügen. Durch Zurücksetzen würden alle drei drei Controller auf ihre jeweiligen Standardwerte gesetzt.

Sie beginnen mit dem Schreiben einer neuen Klasse (ResetFunctionV2) für die neue Funktionalität und ordnen den Benutzereingabe-Zuordnungscode für diese neue Funktion zu.

Anwendungsversion 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 haben Sie Ihre Anwendung mit der Reset-Funktion bereit. Aber jetzt fängst du an, das zu realisieren

Probleme in der TV-Anwendung Version 2

  1. Wenn ein neuer Controller in das Produkt eingeführt wird, müssen Sie den Funktionscode zum Zurücksetzen ändern.
  2. Wenn die Anzahl der Controller sehr hoch wird, haben Sie Probleme, die Referenzen der Controller zu halten.
  3. Der Funktionscode zum Zurücksetzen ist eng mit dem gesamten Code der Controller-Klasse gekoppelt (um Standardwerte abzurufen und festzulegen).
  4. Die Reset-Feature-Class (ResetFunctionV2) kann auf andere unerwünschte Methoden der Controller-Klasse (Adjust) zugreifen.

Gleichzeitig hören Sie von Ihrem Chef, dass Sie möglicherweise eine Funktion hinzufügen müssen, bei der jeder Controller beim Start über das Internet nach der neuesten Version des Treibers aus dem gehosteten Treiber-Repository des Unternehmens suchen muss.

Jetzt denken Sie, dass diese neue Funktion, die hinzugefügt werden soll, der Funktion zum Zurücksetzen ähnelt und Probleme mit der Anwendung (V2) multipliziert werden, wenn Sie Ihre Anwendung nicht neu faktorisieren.

Sie denken über die Verwendung der Vererbung nach, damit Sie die polymorphen Fähigkeiten von JAVA nutzen können, und fügen eine neue abstrakte Klasse (ControllerV3) hinzu

  1. Deklarieren Sie die Signatur der Methode get and set.
  2. Enthält die Implementierung der Anpassungsmethode, die zuvor unter allen Controllern repliziert wurde.
  3. Deklarieren Sie die setDefault-Methode, damit die Rücksetzfunktion mithilfe des Polymorphismus einfach implementiert werden kann.

Mit diesen Verbesserungen haben Sie Version 3 Ihrer TV-Anwendung bereit.

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

        }
    }
}

Obwohl die meisten der in der Problemliste von V2 aufgeführten Probleme außer behoben wurden

Probleme in der TV-Anwendung Version 3

  1. Die Reset-Feature-Class (ResetFunctionV3) kann auf andere Methoden der Controller-Klasse zugreifen (anpassen), was unerwünscht ist.

Auch hier denken Sie daran, dieses Problem zu lösen, da Sie jetzt auch eine andere Funktion (Treiberaktualisierung beim Start) implementieren müssen. Wenn Sie das Problem nicht beheben, wird es auch auf neue Funktionen repliziert.

Sie teilen also den in der abstrakten Klasse definierten Vertrag und schreiben 2 Schnittstellen für

  1. Funktion zurücksetzen.
  2. Treiber-Update.

Und lassen Sie sie von Ihrer ersten konkreten Klasse wie folgt implementieren

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

        }
    }
}

Jetzt wurde das gesamte Problem, mit dem Sie konfrontiert waren, angesprochen und Sie erkannten, dass Sie es mit der Verwendung von Vererbung und Polymorphismus tun konnten

  1. Halten Sie verschiedene Teile der Anwendung lose miteinander verbunden. (Die Komponenten der Funktion "Zurücksetzen" oder "Treiberaktualisierung" müssen nicht über die tatsächlichen Controller-Klassen (Lautstärke, Helligkeit und Farbe) informiert werden. Jede Klasse, die OnReset oder OnStart implementiert, ist für die Funktion "Zurücksetzen" oder "Treiberaktualisierung" akzeptabel Komponenten).
  2. Die Anwendungserweiterung wird einfacher. (Das Hinzufügen eines Controllers wirkt sich nicht auf das Zurücksetzen oder die Treiberaktualisierungsfunktion aus, und Sie können jetzt ganz einfach neue hinzufügen.)
  3. Behalten Sie die Abstraktionsebene bei. (Jetzt kann die Reset-Funktion nur die setDefault-Methode von Controllern und die Reset-Funktion nur die checkForDriverUpdate-Methode von Controllern sehen.)

Hoffe das hilft :-)


3

Der Begriff Überladung bezieht sich auf mehrere Versionen von etwas mit demselben Namen, normalerweise Methoden mit unterschiedlichen Parameterlisten

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

Diese Funktionen können also dasselbe tun, aber Sie haben die Möglichkeit, sie mit einer ID oder einem Namen aufzurufen. Hat nichts mit Vererbung, abstrakten Klassen usw. zu tun.

Überschreiben bezieht sich normalerweise auf Polymorphismus, wie Sie in Ihrer Frage beschrieben haben


2

Überladen ist, wenn Sie 2 Methoden mit demselben Namen, aber unterschiedlichen Parametern definieren

Beim Überschreiben ändern Sie das Verhalten der Basisklasse über eine gleichnamige Funktion in einer Unterklasse.

Polymorphismus ist also mit Überschreiben verbunden, aber nicht wirklich Überladen.

Wenn mir jedoch jemand eine einfache Antwort auf die Frage "Was ist Polymorphismus?" Mit "Überschreiben" gab. Ich würde um weitere Erklärung bitten.


2

Das Überschreiben ähnelt eher dem Ausblenden einer geerbten Methode durch Deklarieren einer Methode mit demselben Namen und derselben Signatur wie die Methode der oberen Ebene (Supermethode). Dadurch wird der Klasse ein polymorphes Verhalten hinzugefügt. Mit anderen Worten, die Entscheidung, welche Level-Methode aufgerufen werden soll, wird zur Laufzeit und nicht zur Kompilierungszeit getroffen. Dies führt zum Konzept der Schnittstelle und Implementierung.


2

Was ist Polymorphismus?

Aus Java Tutorial

Die Wörterbuchdefinition des Polymorphismus bezieht sich auf ein Prinzip in der Biologie, bei dem ein Organismus oder eine Spezies viele verschiedene Formen oder Stadien haben kann. Dieses Prinzip kann auch auf objektorientierte Programmierung und Sprachen wie die Java-Sprache angewendet werden. Unterklassen einer Klasse können ihr eigenes eindeutiges Verhalten definieren und dennoch einige der gleichen Funktionen der übergeordneten Klasse gemeinsam nutzen.

Durch Betrachten der Beispiele und Definition überschreiben sollte das als Antwort akzeptiert werden.

Zu Ihrer zweiten Anfrage:

Wenn Sie eine abstrakte Basisklasse hatten, die eine Methode ohne Implementierung definiert hat, und diese Methode in der Unterklasse definiert haben, ist das immer noch überschreibend?

Es sollte als überschreibend bezeichnet werden.

Schauen Sie sich dieses Beispiel an, um verschiedene Arten des Überschreibens zu verstehen.

  1. Die Basisklasse bietet keine Implementierung und die Unterklasse muss die vollständige Methode überschreiben - (Zusammenfassung)
  2. Die Basisklasse bietet die Standardimplementierung und die Unterklasse kann das Verhalten ändern
  3. Die Unterklasse erweitert die Implementierung der Basisklasse durch Aufrufen super.methodName() als erste Anweisung aufgerufen wird
  4. Die Basisklasse definiert die Struktur des Algorithmus (Template-Methode) und die Unterklasse überschreibt einen Teil des Algorithmus

Code-Auszug:

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

Ausgabe:

Child class: Initialized Chess game
Base class: Defining the flow for Game:
Child class: Validate Chess move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate Chess move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
Child class: Add Chess specific logGameStatistics:
Child class: Initialized TicTacToe game
Base class: Defining the flow for Game:
Child class: Validate TicTacToe move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate TicTacToe move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:

2

Ich denke Leute, ihr mischt Konzepte. Polymorphismus ist die Fähigkeit eines Objekts, sich zur Laufzeit anders zu verhalten. Um dies zu erreichen, benötigen Sie zwei Voraussetzungen:

  1. Späte Bindung
  2. Erbe.

Having said, die Überlastung Mittel , etwas anderes zu überschreiben , je nach der Sprache , die Sie verwenden. Zum Beispiel gibt es in Java kein Überschreiben, sondern Überladen . Überladene Methoden mit einer anderen Signatur als die Basisklasse sind in der Unterklasse verfügbar. Andernfalls würden sie überschrieben (bitte Sie, dass ich jetzt meine, dass es keine Möglichkeit gibt, Ihre Basisklassenmethode von außerhalb des Objekts aufzurufen).

In C ++ ist das jedoch nicht so. Jede überladene Methode, unabhängig davon, ob die Signatur gleich ist oder nicht (unterschiedliche Menge, unterschiedlicher Typ), wird ebenfalls überschrieben . Das heißt, heute ist die Methode der Basisklasse in der Unterklasse nicht mehr verfügbar, wenn sie offensichtlich von außerhalb des Unterklassenobjekts aufgerufen wird.

Die Antwort ist also, wenn es um das Überladen von Java geht . In jeder anderen Sprache kann dies anders sein als in C ++


1

Polymorphismus ist in seiner Bedeutung wahrscheinlicher ... als in Java zu überschreiben

Es geht um ein unterschiedliches Verhalten des SAME-Objekts in verschiedenen Situationen (Programmierweise ... können Sie verschiedene ARGUMENTE aufrufen)

Ich denke, das folgende Beispiel wird Ihnen helfen zu verstehen ... Obwohl es kein reiner Java-Code ist ...

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

Aber wenn wir das ARGUMENT ändern ... wird das VERHALTEN geändert ...

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

Die Person (hier das "Objekt") ist dieselbe ...


1

Polymorphismus ist eine mehrfache Implementierung eines Objekts oder man könnte mehrere Formen eines Objekts sagen. Nehmen wir an, Sie haben eine Klasse Animalsals abstrakte Basisklasse und eine Methode namens, movement()die definiert, wie sich das Tier bewegt. In Wirklichkeit haben wir verschiedene Arten von Tieren, und sie bewegen sich auch unterschiedlich, einige mit 2 Beinen, andere mit 4 und einige ohne Beine usw. Um movement()jedes Tier auf der Erde anders zu definieren , müssen wir Polymorphismus anwenden. Sie müssen jedoch mehr Klassen definieren, z. B. Klassen Dogs Cats Fishusw. Dann müssen Sie diese Klassen aus der Basisklasse erweitern Animalsund ihre Methode movement()mit einer neuen Bewegungsfunktionalität überschreiben, die auf jedem Tier basiert, das Sie haben. Sie können auch verwendenInterfacesum das zu erreichen. Das Schlüsselwort hier ist überschreibend, Überladung ist anders und wird nicht als Polymorphismus betrachtet. Beim Überladen können Sie mehrere Methoden "mit demselben Namen", aber mit unterschiedlichen Parametern für dasselbe Objekt oder dieselbe Klasse definieren.


0

Polymorphismus bezieht sich auf die Fähigkeit einer Sprache, verschiedene Objekte unter Verwendung einer einzigen Schnittstelle einheitlich behandeln zu lassen; Als solches hängt es mit dem Überschreiben zusammen, sodass die Schnittstelle (oder die Basisklasse) polymorph ist. Der Implementierer ist das Objekt, das überschreibt (zwei Flächen derselben Medaille).

Auf jeden Fall lässt sich der Unterschied zwischen den beiden Begriffen besser mit anderen Sprachen wie c ++ erklären: Ein polymorphes Objekt in c ++ verhält sich wie das Java-Gegenstück, wenn die Basisfunktion virtuell ist, aber wenn die Methode nicht virtuell ist, wird der Codesprung statisch aufgelöst . und der wahre Typ, der zur Laufzeit nicht überprüft wird, beinhaltet Polymorphismus die Fähigkeit eines Objekts, sich abhängig von der Schnittstelle, die für den Zugriff darauf verwendet wird, unterschiedlich zu verhalten; Lassen Sie mich ein Beispiel im Pseudocode machen:

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

(Angenommen, makeRumor ist NICHT virtuell)

Java bietet nicht wirklich dieses Maß an Polymorphismus (auch Objekt-Slicing genannt).

Tier a = neuer Hund (); Hund b = neuer Hund ();

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

In beiden Fällen wird nur woff gedruckt, da sich a und b auf Klassenhund beziehen



Tier a = neuer Hund (); a wurde als Hund konstruiert und druckt "woff". Wenn Sie möchten, dass es Schlag druckt, müssen Sie es hochstoßen. ((Tier) a) .makeRumor ()
Chris Cudmore

Das ist Referenz-Upcasting, aber das Objekt ist immer noch ein Hund. Wenn Sie möchten, dass es sich um ein Tier handelt, müssen Sie das Objekt explizit aktualisieren.
Chris Cudmore

Herausgefunden. Frage wurde mit Java getaggt. Sie haben C ++ beantwortet. Sie können in C ++ korrekt sein. Ich bin definitiv richtig in Java.
Chris Cudmore

sollte jedes Mal passieren, wenn ein Kopierkonstruktor beteiligt ist, gibt es eine Referenz fredosaurus.com/notes-cpp/oop-condestructors/… Fall drei Übereinstimmungen; Ignorieren Sie den neuen Operator, der nur zur eindeutigen Erstellung dient.
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());

    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.