Generische Klasse

Hallo ich soll eine gegebene Klasse in eine generische Klasse umschreiben...
Aufgabe:
Schreiben Sie die obige Klasse als generische Klasse mit einem Typparameter für das Attribut item. Als Listeneinträge sollen nur Unterklassen der Klasse Number verwendet werden können.

Meine Frage ist wie ich die Methode "Summe" generisch umschreibe und welchen Typparameter ich "List" in meiner main Methode geben muss
(Ich weiß auch nicht ob meine Lösung bis jetzt überhaupt stimmt :D)
gegebene Klasse:
Code:
public class Test {
    public static void main(String[] args) {
        Liste l = new Liste();
        l.insert(0);
        l.insert(-8);
        l.insert(3);
        l.insert(-5);
        l.insert(3);

        System.out.println(l);
        System.out.println(l.summe());
    }
}
class Liste {
    private int item = -1;
    private Liste next;

    public void insert(int x) {
        Liste l = new Liste();
        if(next == null || next.item > x) {
            l.item = x;
            l.next = next;
            this.next = l;
        } else {
            next.insert(x);
        }
    }
    public String toString() {
        return next == null ? "." : " ? " + next.item + next;
    }
    
    public int summe() {
        if(next == null) {
            return 0;
        }
        int i = next.summe();
        return i + next.item;
    }
}
Meine Klasse:
Code:
public class Test {
    public static void main(String[] args) {
        Liste <T> l = new Liste<T>();  // Fehler
        l.insert(0);
        l.insert(-8);
        l.insert(3);
        l.insert(-5);
        l.insert(3);

        System.out.println(l);
        System.out.println(l.summe());
    }
}
class Liste <T extends Number & Comparable<T>>{
    
    private T item = (T) Integer.valueOf(-1);
    private Liste<T> next;

    public void insert(T x) {
        Liste<T> l = new Liste<T>();
        if(next == null || next.item.compareTo(x) > 0) {
            l.item = x;
            l.next = next;
            this.next = l;
        } else {
            next.insert(x);
        }   
    }
    public String toString() {
        return next == null ? "." : " ? " + next.item + next;
    }
    
    public int summe() {
        if(next == null) {
            return 0;
        }
        int i = next.summe();
        return i + next.item;
    }
}
 
habe das jetzt so gelöst, macht das Sinn?
Sry kenne mich mit Generics noch nicht so gut aus

Code:
public class Test {
    public static void main(String[] args) {
        Liste<Integer>  l = new Liste<Integer>(); 
        l.insert(0);
        l.insert(-8);
        l.insert(3);
        l.insert(-5);
        l.insert(3);

        System.out.println(l);
        System.out.println(l.summe());
    }
}
class Liste <T extends Number & Comparable<T>>{
    
    
    private T item = (T) new Integer(-1);
    private Liste<T> next;

    public void insert(T x) {
        Liste<T> l = new Liste<T>();
        if(next == null || next.item.compareTo(x) > 0) {
            l.item = x;
            l.next = next;
            this.next = l;
        } else {
            next.insert(x);
        }   
    }
    public String toString() {
        return next == null ? "." : " ? " + next.item + next;
    }
    
    public int summe() {
        if(next == null) {
            return 0;
        }
        int i = next.summe();
        
        return i + next.item.intValue();
    }
}
 
Als Listeneinträge sollen nur Unterklassen der Klasse Number verwendet werden können.
Code:
public int summe() {
    if (next == null) {
        return 0;
    }
    int i = next.summe();
    return i + next.item.intValue();
}
Was machst du, wenn deine Liste nicht nur eine Liste<Integer> ist, sondern Liste<Double>? Was wäre dann die int Summe von 0.2 + 0.4 ? Du willst vermutlich dann keinen int als Summe zurückgeben.
Tatsächlich kann man auch nicht T als Rückgabetyp nutzen, da man das neutrale Element 0 dann nicht erzeugt bekommt. `Integer.valueOf(0)` wäre falsch im Falle, dass T=Double ist. `Double.valueOf(0.0)` wäre falsch, im Falle, dass T=Integer ist. Dir bleibt hier nur, Number als Rückgabetyp zu verwenden. Ganz zu schweigen davon, wie man denn zwei beliebige `T`s miteinander addiert. Nutzt man hier immer number.doubleValue() und addiert das Ganze als Double? Wäre ja falsch, wenn T=Long ist, da einige Longs sich nicht als Double abbilden lassen... https://stackoverflow.com/questions/2721390/how-to-add-two-java-lang-numbers#answer-30110482 könnte weiterhelfen.
 
ich danke dir
also wäre das die richtige Lösung

Code:
public Number summe() {
        if (next == null) {
            return 0;
        }
        Number i = next.summe();
        Number j = next.item;
        
        if (i instanceof Double || j instanceof Double) {
            return i.doubleValue() + j.doubleValue();
        } else if (i instanceof Float || j instanceof Float) {
            return i.floatValue() + j.floatValue();
        } else if (i instanceof Long || j instanceof Long) {
            return i.longValue() + j.longValue();
        } else {
            return i.intValue() + j.intValue();
        }
    }
 
ich danke dir
also wäre das die richtige Lösung

Code:
public Number summe() {
        if (next == null) {
            return 0;
        }
        Number i = next.summe();
        Number j = next.item;
       
        if (i instanceof Double || j instanceof Double) {
            return i.doubleValue() + j.doubleValue();
        } else if (i instanceof Float || j instanceof Float) {
            return i.floatValue() + j.floatValue();
        } else if (i instanceof Long || j instanceof Long) {
            return i.longValue() + j.longValue();
        } else {
            return i.intValue() + j.intValue();
        }
    }
Hätte das glaub ich jetzt auch so gemacht.
So castet du dir immer das passende Objekt vom Typ Number, welches du brauchst.

Könnte mir aber durchaus vorstellen, dass es noch eine Elegantere, "Allgemeinere" Lösung gibt.
So das man es nicht jedesmal in das passende Objekt casten muss.
 
Wo wurde denn die Aufgabe gestellt? Vermutlich ist das im Kontext die akzeptierte Lösung...



Allerdings scheitert das wenn z.B. BigInteger benutzt wird, lösen könnte man das mit einer zusätzlich übergebenen Addier-Funktion.
 
K

kneitzel

Also diese Implementation gefällt mir nicht wirklich, denn diese suggeriert erst einmal, dass es für alle Klassen, die von Number abgeleitet wurden, funktioniert. Aber die Implementation ist eben nur für eine klare Anzahl an abgeleiteten Klassen.

Was dies etwas komplexer macht aber denkbar wäre, wäre eben die Übergabe einer Methodenreferenz, die eben zwei T als Parameter hat und ein T zurück gibt (BiFunction<T,T,T>). Das kann dann auch gerne eine Variante geben, die auf diesen Parameter verzichtet und bei bekannten Typen eben dies automatisch setzt und eine Exception wirft, wenn es kein bekannter Typ ist.

Dann wäre diese Problematik umgangen und die Generische Klasse wäre dann generell nutzbar.
 
Passende Stellenanzeigen aus deiner Region:

Oben