UML Diagramm

Diskutiere UML Diagramm im Java Basics - Anfänger-Themen Bereich.
R

Rahza

Ich hänge auch ein wenig an dieser Aufgabe fest. Das Thema Aggregation ist ein wenig verwirrend.

Erstmal im Folgenden der Fehler, der angezeigt wird:
1) test(PublicTests)
java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:86)
at org.junit.Assert.assertTrue(Assert.java:41)
at org.junit.Assert.assertNotNull(Assert.java:712)
at org.junit.Assert.assertNotNull(Assert.java:722)
at PublicTests.test(PublicTests.java:14)

Der Public-Test ist wie folgt:
Code:
import static org.junit.Assert.*;

import java.util.Date;

import org.junit.Test;

public class PublicTests {

    @Test
    public void test() {
        Kunstmuseum kunstmuseum = new Kunstmuseum();
        kunstmuseum.setName("Koblenzer Kunstmuseum");
        assertEquals("Koblenzer Kunstmuseum", kunstmuseum.getName());
        assertNotNull(kunstmuseum.getWerke());
        assertEquals(0, kunstmuseum.getWerke().size());
       
        Kunstwerk kunstwerk1 = new Statue(kunstmuseum);
        Kunstwerk kunstwerk2 = new Gemaelde(kunstmuseum);
        assertEquals(kunstmuseum, kunstwerk1.getMuseum());
        assertEquals(kunstmuseum, kunstwerk2.getMuseum());
       
        assertEquals(2, kunstmuseum.getWerke().size());
       
        kunstwerk1.setName("Werk1");
        kunstwerk1.setPreis(499.99);
        kunstwerk2.setName("Werk2");
        kunstwerk2.setPreis(349.99);
        assertEquals("Werk1", kunstwerk1.getName());
        assertEquals(499.99, kunstwerk1.getPreis(),1E-4);
       
        ((Statue)kunstwerk1).setHoehe(300);
        assertEquals(300,((Statue)kunstwerk1).getHoehe());
       
        Date date = new Date();
        ((Gemaelde)kunstwerk2).setZuletztRestauriertAm(date);
        assertEquals(date, ((Gemaelde)kunstwerk2).getZuletztRestauriertAm());
        assertTrue(kunstwerk2 instanceof Restaurierbar);
        ((Restaurierbar)kunstwerk2).restaurieren();
       
        Person person1 = new Person(kunstwerk1);
        assertEquals(person1, kunstwerk1.getBesitzer());
        person1.setName("Person1");
        assertEquals("Person1",person1.getName());
        assertEquals(1,person1.getKunstwerke().size());
        assertTrue(person1.getKunstwerke().contains(kunstwerk1));
    }

}
Ich sehe gerade, dass im Test die Zeilennummer nicht gezeigt wird. Der Fehler müsste laut Test bei assertNotNull(kunstmuseum.getWerke());
sein
 
mihe7

mihe7

Das Thema Aggregation ist ein wenig verwirrend.
Aggregation bedeutet nur, dass es sich um eine Ganzes-Teile-Beziehung handelt. Das Ganze setzt sich aus Teilen zusammen, wobei die Teile auch ohne das Ganze existieren könn(t)en.

Eine Gruppe ist zum Beispiel eine Aggregation. Die Mitglieder der Gruppe bilden diese. Die Gruppe kann sich jedoch auflösen und die Mitglieder leben trotzdem weiter :)

Anders ist das bei einer Komposition. Auch das ist eine Ganzes-Teile-Beziehung, allerdings können die Teile nicht ohne das Ganze (sinnvoll) existieren. Beispiel: Rechnung und Rechnungsposition.

Die Assoziation ist einfach eine allgemeine Beziehung. Eine Person wurde z. B. bei einer Firma ausgebildet. Hier gibt es keine Ganzes-Teile-Beziehung.

Die verschiedenen Beziehungsarten sind im Java-Code in der Regel nicht (zumindest nicht direkt) voneinander zu unterscheiden.

Der Fehler müsste laut Test bei assertNotNull(kunstmuseum.getWerke());
sein
Dann muss kunstmuseum.getWerke() null liefern.
 
R

Rahza

Danke für die ausführliche Antwort.
Das Problem ist eben die Implementation. In der Theorie habe ich mir viel Material durchgeschaut, um die Unterschiede zwischen Komposition, Aggregation etc. zu verstehen, aber habe wenig Beispiele gefunden, wo man konkret erkennen kann, was die Unterschiede in der Implementation sind.

Auch das Thema Multiplizitäten habe ich im Groben verstanden, aber es gibt noch einige offene Fragen, z.B. wenn ich eine gerichtete Beziehung habe, dann muss ich doch trotzdem entsprechend der Multiplizitäten Attribute bei beiden, in Beziehung stehenden Klassen, hinterlegen. Wie in unserem Beispiel: Die Beziehung zwischen Kunstwerk und Kunstmuseum ist gerichtet, jedoch muss ich in den Attributen sowohl werke als auch museum hinterlegen. Wodran am Code sehe ich also bzw. kann ich sichtbar machen, in welche Richtung es gerichtet ist?

Nun zu meinem konkreten Fehler:
Im Folgenden erstmal mein Code zu Kunstmuseum:
Code:
import java.util.ArrayList;


public class Kunstmuseum {
    
    private String name;
    private ArrayList<Kunstwerk> werke;
 
    public Kunstmuseum() {
        
    }
    public Kunstmuseum(String name) {
        this.werke= new ArrayList<Kunstwerk>();
        this.name=name;
    }

    public void addWerk (Kunstwerk werk) {
        this.werke.add(werk);
    }
    public void removeWerk(Kunstwerk werk) {
        this.werke.remove(werk);
    }

    public ArrayList<Kunstwerk> getWerke(){
        return this.werke;
    }

    public void setWerke(ArrayList<Kunstwerk> werke) {
        this.werke=werke;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
Da im Test ein leeres Kunstmuseum erzeugt wird, müsste die Abfrage doch auch "null" ergeben.
 
mihe7

mihe7

Wie in unserem Beispiel: Die Beziehung zwischen Kunstwerk und Kunstmuseum ist gerichtet,
Dann hättest Du im Diagramm üblicherweise Pfeilspitzen, die die Navigationsrichtung angeben. Eine Beziehung ohne Pfeilspitzen wird üblicherweise für bidirektionale Beziehungen verwendet. Alternative: an jedem Ende eine Pfeilspitze.

D. h. statt A <---> B wird oft nur A ----- B gezeichnet. Das ergibt Sinn, denn bei Aggregation und Komposition kannst Du ja auf der Seite der Raute keinen Pfeil einzeichnen. Daher ist: A <>----- B eine bidirektional navigierbare Beziehung (Aggregation) zwischen A und B, während A <>----> B unidirektional von A nach B ist.

Wodran am Code sehe ich also bzw. kann ich sichtbar machen, in welche Richtung es gerichtet ist?
Naja, um zu einem Objekt navigieren zu können, brauchst Du eine Referenz.

Zum Beispiel A ---- B bedeutet eine bidirektionale Beziehung zwischen A und B, d. h. es gilt A ---> B und A <---- B. Dem entsprechend muss in Klasse A eine Instanzvariable für B und in Klasse B eine Instanzvariable für A existieren.

Bei einer unidirektionalen Beziehung A ---> B würde nur in Klasse A eine Instanzvariable für B existieren.

Da im Test ein leeres Kunstmuseum erzeugt wird, müsste die Abfrage doch auch "null" ergeben.
Wenn der Test den parameterlosen Konstruktor verwendet und setWerke nicht aufgerufen wird, wird getWerke() null liefern.
 
R

Rahza

Ok, damit hättest du schon ein großes Missverständnis aufgeklärt.
Ich bin die ganze Zeit davon ausgegangen, dass Raute für Aggregation zeitgleich auch eine Richtung angibt.

Dann kann man im Grunde schon an Hand der Attribute die "Gerichtetheit" ablesen.
Nun zur Aufgabe:
Ich hatte ursprünglich den Default-Konstruktor nicht drin gehabt, was einen Compiler-Fehler lieferte.
Nun habe ich den hinzugefügt, aber es wird der oben genannte Fehler gezeigt.
Zur Klarstellung: Der Fehler gibt doch an, dass wie temi angegeben hat, eine leere Liste zurückgegeben werden soll. Stattdessen wird aber "null" zurückgegeben. Ist das richtig?
Da schließt sich dann eine weitere Frage an. Muss ich den Default-Konstruktor grundsätzlich drin haben oder ist das jetzt nur weil die das im Test so haben wollen?
 
T

temi

Muss ich den Default-Konstruktor grundsätzlich drin haben oder ist das jetzt nur weil die das im Test so haben wollen?
In deinem Fall: Weil sie es so haben wollen!

Generell sollte man ein Objekt so erzeugen, dass es nach der Erzeugung gültig und "benutzbar" ist, d.h. der Konstruktor sollte mit seinen Parametern ein sinnvolles Objekt erzeugen. Wenn ein parameterloser Konstruktor nicht benötigt wird, dann sollte es ihn auch nicht geben.
 
T

temi

Stattdessen wird aber "null" zurückgegeben. Ist das richtig?
Wir kennen ja deinen Code nicht, aber vermutlich ist das so richtig.

Evtl. sieht es ungefähr so aus:
Java:
class Foo {
    List<Integer> list; // list ist null
 
    List<Integer> getList() {
        return list; // damit wird hier auch null zurückgegeben
    }
}
Abhilfe:
Java:
class Foo {
    List<Integer> list = new ArrayList<>(); // 1. Möglichkeit
 
    Foo() {
        list = new ArrayList<>(); // 2. Möglichkeit
    }

    List<Integer> getList() {
        return list;
    }
}
 
mihe7

mihe7

Der Fehler gibt doch an, dass wie temi angegeben hat, eine leere Liste zurückgegeben werden soll. Stattdessen wird aber "null" zurückgegeben. Ist das richtig?
assertNotNull sagt nur, dass die Referenz nicht null sein darf (was bei Dir aber der Fall ist), ob die Liste an der Stelle leer ist oder nicht, spielt keine Rolle.
 
R

Rahza

Wir kennen ja deinen Code nicht, aber vermutlich ist das so richtig.

Evtl. sieht es ungefähr so aus:
Java:
class Foo {
    List<Integer> list; // list ist null

    List<Integer> getList() {
        return list; // damit wird hier auch null zurückgegeben
    }
}
Abhilfe:
Java:
class Foo {
    List<Integer> list = new ArrayList<>(); // 1. Möglichkeit

    Foo() {
        list = new ArrayList<>(); // 2. Möglichkeit
    }

    List<Integer> getList() {
        return list;
    }
}
Den Code habe ich unter #63 reingestellt, aber ich hab anhand dem Beispiel verstanden was du meinst.
Folgende Fragen tuen sich noch auf:
1. Du hast in dem Beispiel auf der linken Seite eine List genommen und rechts ArrayList; hat das Vorteile bzw. Unterschiede und kann ich auf beiden Seiten ArrayList nehmen?
2. Du hast als Abhilfe zwei Möglichkeiten genannt. Das ist eine Sache, die ich mich ohnehin gefragt habe, da ich das an diversen Stellen jetzt gesehen habe, dass in manchen Klassen in der Attribut-Deklaration direkt eine neue Liste erstellt wird und manchmal erst im Konstruktor. Welchen Unterschied macht das? Auch unabhängig von der Liste ganz allgemein gefragt, wenn ich ein Attribut von irgendeinem Typ entweder direkt in der Attribut-Auflistung erstelle oder aber erst im Konstruktor; macht das einen Unterschied?
 
R

Rahza

Und eine grundsätzliche Frage zur Nutzung dieses Forums:
Bei dem Public-Test von der Uni werden jetzt keine Fehler angezeigt, aber bei der letzten Aufgabe war es auch schon, dass nach der Abgabe ein Extra-Test mit Randfällen hochgeladen wird und obwohl meine Abgabe den Public-Test bestanden hatte, ist der Extra-Test durchgefallen. Frage: Darf ich meine komplette Abgabe hier reinstellen, damit ihr grob drüberguckt oder verstößt das gegen die Richtlinien?
 
T

thecain

Gegen die Richtlinien der Uni vielleicht. Das Forum hat sich ja bald nen Abschluss verdient
 
T

temi

1. Du hast in dem Beispiel auf der linken Seite eine List genommen und rechts ArrayList; hat das Vorteile bzw. Unterschiede und kann ich auf beiden Seiten ArrayList nehmen?
List<> ist ein Interface und ArrayList<> ist eine konkrete Implementation dieses Interfaces. Der Vorteil ist, das du die Implementation einfach austauschen kannst, wenn du vielleicht andere Anforderungen hast. Da der Rest des Codes gegen das Interface programmiert ist, wird das ohne Probleme funktionieren.
Java:
class Foo {
    List<Integer> list;

    Foo(List<Integer> list) {
        this.list = list;
    }
   
    void add(int i) {
        list.add(i);
    }
}

Foo foo1 = new Foo(new ArrayList<Integer>());
Foo foo2 = new Foo(new LinkedList<Integer>());
Du kannst natürlich als Typ auch ArrayList nehmen, das funktioniert auch.

Welchen Unterschied macht das? Auch unabhängig von der Liste ganz allgemein gefragt, wenn ich ein Attribut von irgendeinem Typ entweder direkt in der Attribut-Auflistung erstelle oder aber erst im Konstruktor; macht das einen Unterschied?
In dem Beispiel von #71 macht das keinen Unterschied.

Wenn du es im Konstruktor erstellst, dann hast du z.B. über den Konstruktorparameter noch Einflussmöglichkeiten auf die erstellte Liste, z.B. bietet ArrayList<> auch einen überladenen Konstruktor an. Oder halt wie im Beispiel hier, wo eine komplette Liste als Parameter übergeben wird.
 
Thema: 

UML Diagramm

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben