austauschbarer Code

usrr

Bekanntes Mitglied
Hallo,

ich hoffe das hier ist eine Anfängerfrage und ich bin im richtigen Forum. Wenn nicht, bitte einfach verschieben.

Ich möchte verschieden mathematische Berechnungen durchführen. Um flexible zu bleiben möchte ich dazu ein eine Eigene Zahlenklasse verwenden, die später leicht austauschbar sind. Dazu habe ich eine abstrakte Klasse definiert. In dem Beispiel beschränke ich mich darauf, dass die Zahlen addierbar sind. Als Schnittstelle soll die Zahl durch einen String gesetzt oder gelesen werden können. Ich verwende den Namen Number, obwohl es schon eine sogenannte Klasse gibt.

Number.java
Java:
package Number;

public abstract class Number {
    
    @Override
    abstract public String toString();
    abstract public void fromString(String value);
    abstract public void add(Number number);
    
}

Jetzt entsteht aber ein Problem beim ableiten einer neuen Klasse. ZB:

Java:
public class NumberDouble extends Number {
    ...
    
    @Override
    public NumberDouble add(NumberDouble number) {
        ...
    }

}

Das Problem ist, dass die add-Methode eigentlich so lauten muss:

Java:
public NumberDouble add(Number number)

Aber die add-Methode der abgeleiteten Klasse soll ja mit NumberDouble arbeiten und nicht mit Number!

Wie kann ich hier anders ansetzen um das zu lösen?

Danke schonmal für die Antworten.
 
Zuletzt bearbeitet:

diggaa1984

Top Contributor
Java:
public class NumberDouble extends Number {
    
    @Override
    public Number add(Number number) {
        if (! (number instanceof NumberDouble))
            throw new IllegalArgumentException();
    }

}

so wäre das eine Möglichkeit, weiss aber gerade nicht, wie da der Standard aussieht :)

EDIT: da aber IllegalArgumentException ebenfalls unter die RuntimeExceptions fällt, könntest auch gleich einfach in NumberDouble casten und erhältst eine ClassCastException, welche ebenfalls eine RuntimeException darstellt ^^
 
Zuletzt bearbeitet:

usrr

Bekanntes Mitglied
Ok, das Zahlenobjekt prüft also, ob dass was es als Parameter übergeben bekommt, etwas ist mit dem es Rechnen kann. Ich probiere das mal.

Müsste der Rückgabewert nicht jetzt NumberDouble sein?

Java:
...
@Override
public NumberDouble add(Number number)
...
 
Zuletzt bearbeitet:

diggaa1984

Top Contributor
nein die Signatur der Methode wird ja durch die abstrakte Klasse bestimmt

Java:
public abstract Number add(Number n);
Diese muss auch auch in den Subklassen übernommen werden.
Alles was du mit den Zahlen machen kannst wird ja dann durch die abstrakte Klasse beschrieben, da hast du ja keine Einschnitte. Du arbeitest logisch gesehen auf der Klasse Number, welche Implementierung dahinter liegt, ist ja unerheblich.
 

Michael...

Top Contributor
Aber die add-Methode der abgeleiteten Klasse soll ja mit NumberDouble arbeiten und nicht mit Number!
Das ist mit Generics möglich:
Java:
	abstract class AbstractNumber<T extends AbstractNumber>{
		abstract public T add(T num);
	}
	
	class DoubleNumber extends AbstractNumber<DoubleNumber> {
		public DoubleNumber add(DoubleNumber num) {
			return null;
		}
	}
Eventuell kann man das auch schöner lösen, bin mir da gerade nicht sicher.
 

tfa

Top Contributor
@usrr
Warum wandelst du das Number-Objekt, das der add()-Methode wird, nicht in eine DoubleNumber um? Man kann (mathematisch) sehr wohl Integer, Fließkommazahlen, BigInts, etc. addieren.
Wenn das nicht gehen sollte, was hätte dann add() in der abstrakten Oberklasse zu suchen?
Ein Exception oder sogar ClassCastException zu werfen, würde das ganze Design sinnlos machen. Lieber nicht.
 

usrr

Bekanntes Mitglied
Ok, ich entwickele das Beispiel weiter:

Ich möchte Zahlen natürlich elegant per Konstruktor initialisieren können:

z.B:
Java:
...
Number = NumberDouble("1");
Number = NumberDouble(); // entspricht NumberDouble("0")
...

Dazu habe ich die Klassen entsprechend erweitert:

Number.java
Java:
package Number;

public abstract class Number {

    Number( ) {
        super();
        fromString("0");
    }

    Number( String value ) {
        super();
        fromString(value);
    }

    @Override
    abstract public String toString();
    abstract public void fromString(String value);
    abstract public Number add(Number number);

}

NumberDouble.java
Java:
package Number;

public class NumberDouble extends Number {

    private double value;

    public NumberDouble() {
    }

    public NumberDouble(String value) {
        super(value);
    }

    @Override
    public String toString() {
        return String.valueOf(this.value);
    }

    @Override
    public void fromString(String value) {
        this.value = Double.valueOf(value);
    }

    @Override
    public Number add(Number number) {
        if (!(number instanceof NumberDouble))
            throw new IllegalArgumentException();
        NumberDouble result = new NumberDouble();
        result.fromString(String.valueOf(this.value + Double.valueOf(number.toString())));
        return result;
    }

}

Test.java
Java:
package Number;

public class Test {

    public static void main(String[] args) {

        NumberDouble n1 = new NumberDouble("1");
        NumberDouble n2 = new NumberDouble("2");

        System.out.println( n1 );
        System.out.println( n2 );

    }
}

So, hier erstmal dieser Zwischenschritt. Ich arbeite weiter an dem Beispiel, bis ich zum eigentlichen Fehler bzw. Problem komme.
 

usrr

Bekanntes Mitglied
@usrr
Warum wandelst du das Number-Objekt, das der add()-Methode wird, nicht in eine DoubleNumber um? Man kann (mathematisch) sehr wohl Integer, Fließkommazahlen, BigInts, etc. addieren.
Wenn das nicht gehen sollte, was hätte dann add() in der abstrakten Oberklasse zu suchen?
Ein Exception oder sogar ClassCastException zu werfen, würde das ganze Design sinnlos machen. Lieber nicht.

Es geht darum, dass ich die Kontrolle behalten will und ich die Zahlen mit denen gerechnet werden soll, später leicht austauschen kann. Ich will das aber nicht an hunderten von Stellen im Code machen, sondern einfach nur das zu verwendende Objekt tauschen.

Möglicherweise hast du recht und ich sehe es einfach jetzt noch nicht. Ich versuche mal das Beispiel weiter in Richtung meiner momentanen Lösung zu erweitern und dann sehen wir weiter.
 

diggaa1984

Top Contributor
@usrr
Warum wandelst du das Number-Objekt, das der add()-Methode wird, nicht in eine DoubleNumber um?
Wenn das nicht gehen sollte, was hätte dann add() in der abstrakten Oberklasse zu suchen?
Ein Exception oder sogar ClassCastException zu werfen, würde das ganze Design sinnlos machen.

Würd die ClassCastException nicht eh fliegen, wenn er blind das Objekt castet und es zufällig nich von DoubleNumber sein sollte!?

Also die kann er in dem Fall ja nicht ausblenden. Die Idee mit instanceof ist in Anbetracht des Casts eigentlich unnötig, hatte ich ja oben schon korrigiert.


Java:
public Number add(Number number) {
    if (!(number instanceof NumberDouble))
            throw new IllegalArgumentException();

    NumberDouble result = new NumberDouble();
    result.fromString(String.valueOf(this.value + Double.valueOf(number.toString())));
    return result;
}

Wäre es nich viel intuitiver auf den values der Objekte zu arbeiten, statt immer in String und zurück zu wandeln?
Java:
public Number add(Number number) {
    NumberDouble n = (NumberDouble) number; //wirft ClassCastException
   
    return (new NumberDouble(n.value + this.value));
}

EDIT:

Die Konstruktoren müssten auch noch angepasst werden. Wo landet denn der Superaufruf in der abstrakten Klasse? Und der Standardkonstruktor aus NumberDouble kann doch auf den Standardkonstruktor der abstrakten Klasse verweisen.

Java:
public abstract class Number {
    
    public Number() {
        this("0");
    }

    public Number(String value) {
        fromString(value);
    }
}

public class DoubleNumber extends Number {
    
    public Number() {
        super();
    }

    public Number(String value) {
        super(value);
    }
}
 
Zuletzt bearbeitet:

diggaa1984

Top Contributor
ach stimmt, seh grad, die abstrakte Klasse hat ja gar keine Klassenvariable .. oeh dann geht das natürlich nich wie ich das geschrieben hab ^^
 

usrr

Bekanntes Mitglied
Doch es funktioniert, wenn ich den Konstruktor der NumberDouble zufüge:

Java:
    public NumberDouble(double value) {
        super();
        this.value = value;
    }
 

usrr

Bekanntes Mitglied
So einen Schritt weiter:

Das ist das momentane Hauptprogramm:

Java:
package Number;

public class Test {

    public static void main(String[] args) {
        NumberDouble n = new NumberDouble("2");
        System.out.println( new NumberDouble(1).add(n) );
    }

}

Da ist ja später noch andere NumberObjekte geben wird, möchte ich keine speziellen Klassen im Hauptcode stehen haben.

Ich möchte, dass über einen Platzhalter lösen (weil ich es nicht besser weiß):

UseThisNumber.java
Java:
package Number;

class UseThisNumber extends NumberDouble {

    UseThisNumber() {
        super();
    }

    UseThisNumber(String value) {
        super(value);
    }

}

Komischerweise funktioniert jetzt das Hauptprogramm. Natürlich muss überall wieder auf den Konstructor über Text umgestellt werde.

Java:
package Number;

public class Test {

    public static void main(String[] args) {

        UseThisNumber n = new UseThisNumber("5");

        System.out.println( new UseThisNumber("7").add(n) );

    }
}

Ich werde, jetzt erstmal meinen Code anpassen und sehen ob ich weiter komme. Evtl. ist mein Problem schon gelöst.
 

diggaa1984

Top Contributor
wo ist jetzt der Sinn hinter UseThisNumber?

die idee ist ja die abstrakte Klasse zu nutzen:
Java:
package Number;
 
public class Test {
 
    public static void main(String[] args) {
        Number n = new NumberDouble("2");
        System.out.println( n.add(new NumberDouble("1")) );
    }
 
}
 

usrr

Bekanntes Mitglied
Die Idee bzw. Not dahinter ist, dass ich an vielen Stellen im Algorithmus Zahlen erschaffe ... also ...

Java:
....
Number Zahl1 = new NumberDouble("1");
...
Number Zahl2 = new NumberDouble("2");
...

Ich will nicht alle Stellen ersetzen müssen, deswegen benutze ich die Zusatzklasse UseThisNumber.
 

usrr

Bekanntes Mitglied
Vorher
Java:
....
Number Zahl1 = new NumberDouble("1");
Number Zahl2 = new NumberDouble("2");
...
Number Zahl100 = new NumberDouble("100");
...

Beim Wechsel zwischen NumberDouble und NumberBigDecimal, müsste der Code an 100 Stellen geändert werden:

Java:
....
Number Zahl1 = new NumberBigDecimal("1");
Number Zahl2 = new NumberBigDecimal("2");
...
Number Zahl100 = new NumberBigDecimal("100");
...

Wenn ich eine Klasse dazwischen schalte, muss man nur noch an einer Stelle ändern.
 

diggaa1984

Top Contributor
du möchtest dann Beispielsweise die Angabe hinter extends in der Klasse UseThisNumber ändern und damit die Änderung in den ganzen Zeilen umgehen?
 

usrr

Bekanntes Mitglied
du möchtest dann Beispielsweise die Angabe hinter extends in der Klasse UseThisNumber ändern und damit die Änderung in den ganzen Zeilen umgehen?

Genau das ist mein Plan!

Zum eigentlichen Problem. Nach dem Überarbeiten meines Codes läuft es jetzt. Ich denke ich weiß auch was mein Fahler war. Ich habe Number und UseThisNumber durcheinander geworfen.

Ich habe alles so geändert, dass für Rückgabewerte immer die abstrakte Klasse Number genommen wird, aber immer wenn mit new eine Zahl erzeugt wird verwende ich UseThisNumber. Wenn ich es jetzt so schreibe, hört sich das auch logisch an. Keine Ahnung warum ich in diese Erkenntnis knapp einen Tag investieren musste.

Ich markiere das Thema erstmal als gelöst, denke aber, dass noch Probleme auftreten könnte.

Vielen Dank!

Was noch offen ist, wäre auch die alternative Lösung von Michael... mit den Generics. Viel verstnden habe ich davon nicht :)
Michael... hat gesagt.:
Das ist mit Generics möglich:
Java:
    abstract class AbstractNumber<T extends AbstractNumber>{
        abstract public T add(T num);
    }
    
    class DoubleNumber extends AbstractNumber<DoubleNumber> {
        public DoubleNumber add(DoubleNumber num) {
            return null;
        }
    }
Eventuell kann man das auch schöner lösen, bin mir da gerade nicht sicher.
 

diggaa1984

Top Contributor
Ist es später nicht so, dass verschiedene Zahlformate parallel existieren (Ganzzahlen und Kommazahlen und weiss ich was noch alles)

Da müsstest du für jede dieser Typen eine Art "UseThisXNumber"-Klasse schreiben?!

Vielleicht wäre etwas in der Art intuitiver auch in der Verwendung:
Java:
public class NumberFactory {

    public static Number getDoubleNumber() {
        return getDoubleNumber(null);
    }

    public static Number getDecimalNumber() {
        return getDecimalNumber(null);
    }

    public static Number getDoubleNumber(String value) {
        if (value == null)
            return new DoubleNumber(); //oder eben eine andere Implementierung

        return new DoubleNumber(value); //oder eben eine andere Implementierung
    }

    public static Number getDecimalNumber(String value) {
        if (value == null)
            return new DecimalNumber(); //oder eben eine andere Implementierung

        return new DecimalNumber(value); //oder eben eine andere Implementierung
    }

das kann man ja beliebig weiterspinnen .. finde ich rein aus OOP-Aspekten sauberer, als eine Klasse zu erstellen die eine andere erweitert nur um eine spezielle Implementierung zu verwenden
 

usrr

Bekanntes Mitglied
Aus jetziger Sicht soll nur ein Zahlenformat verwendet werden, was sich aber später ändern könnte.

Wenn ich deinen Vorschlag richtig interpretiere würdest du eine Methode Implementieren, die Zahlen erzeugt, z.B.
Java:
Number giveMeNewNumber(){...}

Dann müsste ich immer nur diese Methode ändern. Das wäre allerdings eine Option.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
G Code Editieren Java Basics - Anfänger-Themen 19
tomzen Programm ignoriert in der Ausführung Code Java Basics - Anfänger-Themen 8
O Obfuscateter Code lässt sich nicht ausführen? Java Basics - Anfänger-Themen 7
M Code aus IntelliJ in "Textform" für Word-Paper? Java Basics - Anfänger-Themen 10
T Kann mir jemand wörtlich erklären, was in dem Code genau passiert? Java Basics - Anfänger-Themen 1
Ü Dead Code im Programm? Java Basics - Anfänger-Themen 13
I QR code in Java selber generieren Java Basics - Anfänger-Themen 5
terashy VS Code Project run error Java Basics - Anfänger-Themen 10
JaZuDemNo Code Erklärung Java Basics - Anfänger-Themen 3
M Connect-4-Code analysieren Java Basics - Anfänger-Themen 2
N BMI Rechner Was haltet ihr von dem Code habt ihr Verbesserungsvorschläge weil design teschnisch ist das nicht das geilste würde das gerne überarbeiten Java Basics - Anfänger-Themen 12
W In alten Code zurück- und dort wieder zurechtfinden? Java Basics - Anfänger-Themen 17
T code so schreiben das er von sich selber anpasst (code soll die anzahl aller bustaben bestimmen) Java Basics - Anfänger-Themen 16
J Frage zu einem "Taschenrechner" code Java Basics - Anfänger-Themen 9
T Fehlercode bei code der das Alter ausrechnet Java Basics - Anfänger-Themen 2
T Text einlesen code was kommt dahin? Java Basics - Anfänger-Themen 1
jhfjeh Strukturgramm in code Java Basics - Anfänger-Themen 11
D Tipps zum Code Java Basics - Anfänger-Themen 24
W Java-Code mit Array Java Basics - Anfänger-Themen 14
W Java-Code Java Basics - Anfänger-Themen 2
W Java code- TicTac toe Java Basics - Anfänger-Themen 51
W Java-code Java Basics - Anfänger-Themen 8
W Java-code Java Basics - Anfänger-Themen 9
W Java-Code erklären Java Basics - Anfänger-Themen 6
ohneInformatik; For Schleife. Was macht dieser Code?? Java Basics - Anfänger-Themen 5
Say Fehlenden Code finden in einer while-Schleife? Java Basics - Anfänger-Themen 11
Say 2-DIM Array Code lesen und verstehen Java Basics - Anfänger-Themen 5
Say Stelle in Code herausfinden, wie geht man vor? Java Basics - Anfänger-Themen 12
Say do-While Code Ausführung Java Basics - Anfänger-Themen 3
W Rückfrage zur Programmgestaltung (clean code) Java Basics - Anfänger-Themen 12
M intelliJ auf neuem PC, plötzlich kein Code Java Basics - Anfänger-Themen 3
Pinhg Sound in Greenfoot Code einbinden Java Basics - Anfänger-Themen 2
C Java boolean Code läuft nicht Java Basics - Anfänger-Themen 5
I Code für Bezahlsystem (auch bei Offline Aktivität) Java Basics - Anfänger-Themen 7
J Größter gemeinsamer Teiler: mein Code Java Basics - Anfänger-Themen 6
B Den Dateipfad einer Java Datei durch Code in Selbiger finden? Java Basics - Anfänger-Themen 10
A Wie könnte man diesen Code kürzer machen ? Java Basics - Anfänger-Themen 7
J Frage zu meinem Code (OOP) Java Basics - Anfänger-Themen 4
Alen123 Warum funktioniert mein Code nicht? Java Basics - Anfänger-Themen 64
Max246Sch Frage zu Währungsrechner Code Java Basics - Anfänger-Themen 2
S Hilfe bei Umänderung von Java Code Java Basics - Anfänger-Themen 16
I Code wird nicht ausgeführt Java Basics - Anfänger-Themen 2
K Wie kann man diesen Code schnell und effizient interpretieren (Man hat nur 4 Minuten) Java Basics - Anfänger-Themen 3
R ISBN-10-Code überprüfen Java Basics - Anfänger-Themen 7
I Bitte um Hilfe zu unterstehenden Code Java Basics - Anfänger-Themen 6
I Interface von einer EJB Klasse, um Code zu reduzieren Java Basics - Anfänger-Themen 1
I HTML Code säubern Java Basics - Anfänger-Themen 4
B Brauche Hilfe zu einem Code Java Basics - Anfänger-Themen 5
Temsky34 Problem mit dem Code Java Basics - Anfänger-Themen 17
N Fehler im Code (Aufgabe für Anfänger) Java Basics - Anfänger-Themen 11
N Java-Code abwärtskompatibel machen Java Basics - Anfänger-Themen 4
J Erste Schritte Was mache ich in meinem Code falsch. Java Basics - Anfänger-Themen 3
Ameise04 Variablen Inhalt einer Variable im Code verwenden? Java Basics - Anfänger-Themen 9
S Compiler-Fehler Nicht adressierbarer Code ( Non-addressable code ) Java Basics - Anfänger-Themen 5
Aemulit Java Schaltjahr berechnen Code Java Basics - Anfänger-Themen 7
A Code Problem Java Basics - Anfänger-Themen 6
C Fehler im Code Java Basics - Anfänger-Themen 10
A Zu einem bestimmten Ort im Code springen Java Basics - Anfänger-Themen 11
L Ist der Code richtig Java Basics - Anfänger-Themen 3
josfe1234 code vereinfachen Java Basics - Anfänger-Themen 15
nonickatall Ausführbarkeit von Code testen bzw. Remote Debugging Java Basics - Anfänger-Themen 4
F Frage betreff Programm mit dem man C++-Code in JAVA-Code übersetzen lassen kann Java Basics - Anfänger-Themen 2
S Fehler bei Code mit SubStrings für mich nicht auffindbar. Java Basics - Anfänger-Themen 4
G Programm Code Java Basics - Anfänger-Themen 5
C Code zusammenfassen Java Basics - Anfänger-Themen 5
I Erklärung zum Java Code Java Basics - Anfänger-Themen 2
T Programmablaufsplaninterpretation in Code umformen Java Basics - Anfänger-Themen 1
dieter000 Kurze Frage kann mir ejmand kurz diesen Code erklären, bzw wie man die zeilen erklärt und so Java Basics - Anfänger-Themen 1
AlexVo String zu Java Anweisung getString("*** java code ***") Java Basics - Anfänger-Themen 19
M ISBN-Code Java Basics - Anfänger-Themen 26
B Zeitgleiches Arbeiten am Code mit mehreren Personen? Java Basics - Anfänger-Themen 7
S Wie kann ich bei diesem Code erreichen, das als Ergebnis hier 15 herauskommt? Java Basics - Anfänger-Themen 23
N Kann man den Code vereinfachen? Java Basics - Anfänger-Themen 25
marcooooo Code erklären Java Basics - Anfänger-Themen 28
marcooooo Code erklären Java Basics - Anfänger-Themen 4
S Advent of Code Day4 Java Basics - Anfänger-Themen 4
B Nach eingefügtem Code erkennt Compiler keine Instanzvar und meldet SyntaxError Java Basics - Anfänger-Themen 2
Gaudimagspam Caesars Code entziffern in Java Java Basics - Anfänger-Themen 8
Lukasbsc Wie kann ich meinen Code optimieren? Java Basics - Anfänger-Themen 4
NeoLexx equals()-Methode Verständnis Frage anhand Code Beispiel Java Basics - Anfänger-Themen 22
I Input/Output Code wird doppelt ausgeführt Java Basics - Anfänger-Themen 3
T Main startet nicht bei vorgegebenen Code Java Basics - Anfänger-Themen 41
B Frage zum Code verständnis im Resultat Java Basics - Anfänger-Themen 10
J Fehler im Code, aber ich weiß nicht wieso! Java Basics - Anfänger-Themen 6
S Mehrere Probleme im Code Java Basics - Anfänger-Themen 7
M Code nur für Cracks? Crack the Passwort Übung Java Basics - Anfänger-Themen 7
parrot Code entferneJedeZweiteZiffer Java Basics - Anfänger-Themen 6
G Code kürzen Java Basics - Anfänger-Themen 5
Bluedaishi Source Code Signieren Java Basics - Anfänger-Themen 22
L Best Practice Code Refactoring für Methoden mit fast gleicher Aufbau Java Basics - Anfänger-Themen 6
L Best Practice Code refactern Java Basics - Anfänger-Themen 30
G code kürzen Java Basics - Anfänger-Themen 16
A Code umschreiben Java Basics - Anfänger-Themen 6
Torsten.E JavaFX mit Visual Studio Code verwenden Java Basics - Anfänger-Themen 1
C Beispiel-Code mit Pair wird nicht compiliert. Java Basics - Anfänger-Themen 8
X Reverse algorithm engineering (Java code) Java Basics - Anfänger-Themen 6
T Bufferedwriter code Nullpointerexception Java Basics - Anfänger-Themen 4
V Switch Methode macht Code kaputt Java Basics - Anfänger-Themen 18
R Was muss ich an meinem Code ändern? Java Basics - Anfänger-Themen 2
S Bewertet meinen Code - Part 1 Java Basics - Anfänger-Themen 8

Ähnliche Java Themen

Neue Themen


Oben