Home > Informatik > Stufe Q1 > Referenzen > dynamische List

15.42 Quelltext-Analyse, Teil 3

getContent()

Die sondierende Methode getContent "holt" konkreten Inhalt (content) aus der Liste heraus. Nicht irgendwelchen Inhalt, sondern den Inhalt des aktuellen Listen-Elementes.

    /**
     * Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird das
     * aktuelle Objekt zurückgegeben, andernfalls (hasAccess() == false)
     * gibt die Anfrage den Wert null zurück.
     */
    public Object getContent()
    {
       if (hasAccess())
          return act.wert;
       else
          return null;    
    }

Das setzt natürlich vorraus, dass es überhaupt ein aktuelles Element gibt. Daher wird die Bedinung hasAccess() am Anfang der Methode überprüft. Wenn es kein aktuelles Element gibt, wird einfach der Wert null zurückgeliefert.

Gibt es jedoch ein aktuelles Element, so wird in das Element "hineingeguckt" und das Attribut wert dieses Elementes wird zurückgeliefert.

Nachteile dieses Verfahrens

Und damit sind wir auch schon beim Schwachpunkt dieses Vorgehens angekommen. Die dynamische ist ist nur scheinbar generisch. Sie verwaltet zwar Objekte, so dass das Testprogramm zum Beispiel mit der Klasse Bruch wunderbar funktioniert, aber sie verwaltet keine beliebigen Objekte. So wie die Klasse List hier implementiert wurde, müssen die Objekte ein Attribut wert besitzen. Bei der Methode next haben wir ja bereits gesehen, dass die Objekte außerdem ein Attribut nachfolger besitzen müssen.

Aus diesem Grund wurde innerhalb der Klasse List eine Klasse Knoten angelegt, die als Vorlage für die zu verwaltenden Objekte dient:

    public class Knoten
    {
       Object wert;
       Knoten nachfolger;
       
       public Knoten(Object w, Knoten n)
       {
          wert = w;
          nachfolger = n;
       }
    }

Diese Klasse ist nun aber fast generisch, kann also in der Komponente wert beliebige Objekte speichern. Nur "fast" generisch, weil rein technisch gesehen nicht die Bedingungen für generische Klassen erfüllt sind - aber das ist ein Thema, das hier zu weit führen würde.

Wie gelangt man an den Inhalt?

Schauen wir uns dazu ein Testprogramm an, und zwar in mehreren Versionen, damit Sie die Problematik leichter verstehen können.

Version 1
public class Test
{
    List l;

    public Test()
    {
       l = new List();
       l.append(new Bruch(1,1));
       l.append(new Bruch(1,2));
       l.append(new Bruch(1,3));
       l.toFirst();
       System.out.println(l.getContent());
    }
}

Die Liste besteht aus drei Elementen, von denen das erste auch das aktuelle ist. Dann wird getContent aufgerufen und mit System.out.println ausgegeben. Hier das Ergebnis:

Bruch@4289c350

Dieses Ergebnis kann nun so interpretiert werden: An der Adresse @4289c350 ist ein Objekt der Klasse Bruch gespeichert. Damit haben wir also nicht den Content (Inhalt) des ersten Elementes ausgegeben, sondern nur die Adresse im Arbeitsspeicher.

Version 2
public class Test
{
    List l;

    public Test()
    {
       l = new List();
       l.append(new Bruch(1,1));
       l.append(new Bruch(1,2));
       l.append(new Bruch(1,3));
       l.toFirst();
       
       Bruch b = l.getContent();
       b.show();
    }
}

Beim Kompilieren wird eine Fehlermeldung angezeigt: incompatible types: java.lang.Object cannot be converted to Bruch.

Was ist hier falsch gelaufen?

Die Liste hat keine Ahnung davon, dass irgendjemand mal vorhat, irgendwann Objekte der Klasse Bruch in ihr zu speichern. Davon weiß die Klasse List nichts. Wenn man also getContent aufruft, wird nur eine Referenz auf irgendein Objekt, also eine Instanz der Klasse Object, geliefert.

Und so intelligent ist der Compiler nicht, dass er sieht:

Buch b = l.getContent();

"Aha, da soll also etwas aus der Liste herausgeholt und dann als Objekt der Klasse Bruch interpretiert werden". Das kann der Compiler so nicht leisten. Aber es gibt da ja einen Trick, den wir bereits früher kennengelernt haben, das sogenannte Typecasting. Versuchen wir es jetzt also mal mit der dritten Variante.

Version 3
public class Test
{
    List l;

    public Test()
    {
       l = new List();
       l.append(new Bruch(1,1));
       l.append(new Bruch(1,2));
       l.append(new Bruch(1,3));
       l.toFirst();
       
       Bruch b = (Bruch) l.getContent();
       b.show();
    }
}

Und endlich funktioniert die Ausgabe des Bruchs! Es wird 1/1 ausgegeben, also der Bruch-Inhalt des ersten Listen-Elements.