Override zeigt keinen Effekt

mot

Mitglied
Hallihallo an alle Leser 🙂

heute wende ich mich mit einem Override-Problem an Euch und hoffe, dass Ihr Licht in mein Dunkel bringen könnt.

Im Code unter IntelliJ wird angezeigt, dass das Override verwendet werden würde, allerdings wird beim Ausführen die ursprüngliche, nicht die überschriebene Version ausgegeben.

Ich übersehe wieder mal irgendetwas, weil ich es wohl noch nicht richtig verstanden habe...

Ursprungscode (stark eingekürzt):
Java:
public class Konto {

    public static int guthaben;

    //Betrag verringern
    public void mindern(int in) {
        guthaben = guthaben - in;
        System.out.println("Der Kontostand ist jetzt " + guthaben);
    }

    //Konstruktor
    public Konto() {
    }
    public Konto(String inhaber) {
    }

}

überschreibender Code:
Java:
public class BoesesKonto extends Konto{

    @Override
    public void mindern(int in) {
        guthaben = guthaben;
        System.out.println("Der Kontostand ist immer noch" + guthaben);
    }
}

und der Aufruf (wieder stark eingekürzt:
Java:
import java.util.Scanner;

public class Bank {

    public static void main(String[] args) {
        System.out.println("a-Einzahlen, b-Abheben, c-Überweisen");
        System.out.println(("andere Eingabe -> Konto erstellen"));
        Scanner scanner = new Scanner(System.in);
        String auswahl = scanner.next();

        if (auswahl.equals("a")) {
            System.out.println("Wie viel soll eingezahlt werden");
            Konto temp = new Konto();
            temp.erhoehen(Integer.valueOf(scanner.next()));
        }
        
        else if (auswahl.equals("b")) {
            System.out.println("Wie viel soll ausgezahlt werden");
            Konto temp = new Konto();
            temp.mindern(Integer.valueOf(scanner.next()));
        }
......

Manchmal hab ich ja Glück und beim Posten fällt es mir "wie Schuppen von den Augen" und ich kann mir den Beitrag sparen. 😅 klappt nur heute leider nicht
 
ok - interessanter Hinweis.

Dann hab ich tatsächlich einen Denkfehler.
Mein Gedanke war es, eine Klasse (BoesesKonto) zu erstellen, die den Inhalt von "Konto" erbt, um dann dort die Methode zum Verringern zu verändern. Hierzu wollte ich die Hauptdatei "Bank" nicht verändern müssen, weil ich meine, dass der Zugriff normalerweise ja gar nicht existieren dürfte (als böser Entwickler). Oder?

Nach Deinem Hinweis zu urteilen, bleibt mir aber gar nichts anderes übrig, als in Bank den Code so zu verwenden:

Java:
BoesesKonto temp = new BoesesKonto();

Das funktioniert zwar - habs gerade ausprobiert - widerspricht das aber nicht dem eigentlichen Gedanken?
 
Ich bin mir gerade unsicher, was Du genau machen willst.

Generell ist es üblich, dass man Klassen möglichst entkoppelt. So wird oft gegen Interfaces implementiert.

Wenn es diverse Konten geben kann, dann ist es der Verwaltung egal, was für ein Konto Du hast. Du hast also eine Klasse, die Konten verwaltet:
List<Konto> konten;

Und dann gibt es eine Methode, um Konten hinzu zu fügen. Also etwas wie:
void addKonto(Konto newKonto);

Dann hast Deine Implementationen von Konto. Das kann dann sowas sein wie "GuthabenKonto", "DispoKonto", .... Evtl. gemeinsame Implementationen a.la "AbstractKonto" oder "BasisKonto" - es kann also eine Vererbungshierarchie geben. Dabei ist es der Verwaltung egal, was für Konten es gibt. Du kannst also beliebige neue Implementationen hinzufügen. Da könnte also auch Deine Klasse BoesesKonto existieren.

Und dann ist die Frage, wie hier die Instanzen erzeugt werden. Da gibt es in der Praxis viele Möglichkeiten. Einfache Factory Klassen wären denkbar. Oder Du baust eine Plugin Schnittstelle (z.B. über ServiceLoader - dann könntest Du z.B. nach einem String suchen, obe es dazu eine Implementation gibt). Viele Frameworks haben da auch eigene Ideen, so kann man sowas z.B. in Konfigurationsdateien packen ... (Könnte Beans geben und dann werden die in einer beans.xml konfiguriert oder so) Da stehen Dir also alle Türen offen.


Wobei sowas eher unüblich ist. Der übliche Weg ist, die Konten zu analysieren: Was für Verhalten gibt es? In der Regel sind diese immer gleich. Es gibt dann halt Zinsen für Guthaben und für Überziehungen. Es gibt diverse Limits. Es gibt Gebühren. Und dann kann man die diversen Kontentypen als Daten implementieren. Es gibt also nur eine Klasse Konto und auch eine Klasse KontoTyp. Und dann kann man bei einem Konto ein KontoTyp festlegen. Und die KontoTypen sind dann einfache Datensätze. Ggf. mit Versionierungen, d.h. die Zinsen ändern sch zu bestimmten Zeitpunkten und so ....
 
ok - langsam.
Das muss ich jetzt erst mal verdauen.

Worum es mir hier geht - als Laie noch ganz am Anfang meiner Programmiererfahrungen - ist den Zusammenhang zu verstehen, wann wie vererbt und überschrieben wird.

Es handelt sich hier wieder um eine zu lösende Aufgabe. Zunächst sollte ich eine Klasse Konto mit den Methoden Ein- und Auszahlen erstellen. Dann über die Klasse Bank eben diese Methoden nutzen. Im Anschluss daran, sollte die Methode für das Auszahlen als "böser Entwickler" so überschrieben werden, dass sie den Wert beim Auszahlen nicht mehr verringert.

Ich habe hier noch gar nicht über Dispokonten, Schnittstellen, Zinsen oder so nachgedacht. Ganz einfach nur versucht herauszufinden, weshalb meine Methode zwar angeblich überschrieben wird, aber nicht die richtige Ausgabe kommt.

Bei der Aufgabenstellung als "böser Entwickler" muss ich doch davon ausgehen, dass ich nicht unbedingt Schreibzugriff auf den Code der Klasse "Bank" habe, sondern einen anderen Weg finden muss, damit die Methode die dort aufgerufen wird überschrieben wird. Daher der Gedanke eine erbende Klasse (BösesKonto) zu verwenden, die die Methode aus "Konto" überschreibt.

Also "eigentlich" ja was ganz einfaches. Dachte ich.
 
Wenn die Klasse Bank die Instanzen von Klasse selbst erzeugt, dann hast Du da keine Möglichkeit, da einzugreifen. Du musst ja an der Stelle, an der die Instanz erzeugt wird, eingreifen um statt einer Instanz von Konto eine Instanz von BoesesKonto zu erstellen. Das wäre bei Dir in der Klasse Bank und damit brauchst Du da Zugriff.

Das wäre die Lösung bezüglich der Idee, das über das Thema "Überschreiben einer Methode" zu lösen.

Wenn Du darauf keinen Zugriff hast, dann gibt es natürlich auch Ansätze. Die Java Klassen, die Du schreibst, werden ja in .class Dateien übersetzt welche dann beim Ausführen vom ClassLoader geladen werden. Die Einzelheiten sind dann in einer Instanz der Klasse Class.
Es ist natürlich denkbar, die Klasse Konto nach dem Laden noch zu verändern. Das ist dann aber mehr ein Frickeln und hat mir einer Software Entwicklung, die Du lernen sollst, nichts zu tun. (Es gibt aber Bereiche, in denen das durchaus notwendig ist und auch gebraucht wird. Aber das kannst Du guten Gewissens derzeit komplett ignorieren!)
 
😅ok - bin auch erst mal froh, wenn ich mich nicht noch mit Besonderheiten beschäftigen muss.

Ich vermerke also für mich, dass ich auf jeden Fall schreibenden Zugriff auf "Bank" benötige, damit ich die Klasse "BoesesKonto" ansprechen und damit die Methode aus "Konto" überschreiben kann.

Gibt es denn alternativ die Möglichkeit die Instanz direkt in der Klasse "Konto" zu erzeugen und damit dann meinem Ursprungsgedanken zu folgen? (Auch auf die Gefahr hin, dass der "gute Programmierer" dann einen schlechten Programmierstil an den Tag gelegt hätte). Oder verrenne ich mich da jetzt?

Bin erst auf die Idee gekommen, weil Du oben geschrieben hast, "wenn die Klasse Bank die Instanzen von Klasse selbst erzeugt,..."
 
Gibt es denn alternativ die Möglichkeit die Instanz direkt in der Klasse "Konto" zu erzeugen und damit dann meinem Ursprungsgedanken zu folgen?
Du kannst an beliebiger Stelle eine Methode haben, die Konto zurück gibt. Das kann etwas sein wie:
Java:
public static Konto createKonto() {
    return new Konto();
}

Und Konto kann z.B. einen Namen beinhalten. Also wäre denkbar, dass man die Method modifiziert in der Form:
Java:
public static Konto createKonto(String name) {
    if ("KonradN".equals(name)) {
        return new BoesesKonto(name);
    }
    
    return new Konto(name);
}

Das kann in einer Klasse KontoFactory sein und Bank ruft dann halt `KontoFactory.createKonto(name) auf statt ein new Konto() aufzurufen.

Man braucht dann keinen Zugriff auf die Klasse Bank sondern auf die Klasse KontoFactory.
 
ich habe versucht, das einmal umzusetzen, bekomme aber nun wieder Fehler, die bei mir mal wieder noch auf völliges Unverständnis treffen.

mein Code sieht nun wie folgt aus:

Bank:
Java:
public class Bank {

//Useraktion
    public static void main(String[] args) {
        System.out.println("a-Einzahlen, b-Abheben, c-Überweisen");
        System.out.println(("andere Eingabe -> Konto erstellen"));
        Scanner scanner = new Scanner(System.in);
        String auswahl = scanner.next();

        if (auswahl.equals("a")) {
            System.out.println("Wie viel soll eingezahlt werden");
            Konto.erhoehen(Integer.valueOf(scanner.next()));
            System.out.println("Das Konto hat jetzt" + Konto.guthaben);
        }

in Konto steht jetzt:
Java:
public class Konto {

    public static int guthaben;

    public static Konto erhoehen(int in) {
        guthaben = guthaben + in;
        Konto temp = new Konto();
        return new Konto();
    }

und mein gescheiterter Versuch für BoesesKonto sieht so aus:
Java:
public class BoesesKonto extends Konto{

    @Override
    public Konto erhoehen(int in) {
        guthaben = 100;
        Konto temp = new Konto();
        return new Konto();
    }
}

Ohne die Angabe von "static" in BoesesKonto kommt es zu der Information, dass ich "erhoehen" nicht außer Kraft setzen kann und keine Methode aus dem Supertyp überschreibt.

Mit dem Versuch "static" anzugeben der Hinweis, dass statische Methoden nicht mit der Override-Annotation versehen werden kann.

Also doch nicht so einfach wie gedacht.
 
Wie Du richtig erkannt hast: Das mit dem static ist Quatsch. Du willst ja mehrere Instanzen von Konto haben und jede Instanz soll ein eigenes Guthaben haben. Und erhöhen erhöht den Kontostand einer Instanz. Daher muss da static überall raus.

Die static Methode ist eine Methode, die ein neues Konto erzeugt. Und die kommt in eine eigene Klasse (Oder von mir aus auch in Bank oder Konto ... technisch ist es egal.)
 

Neue Themen


Zurück
Oben