ArrayList`s in Klassen mit Getter/Setter

Guten Abend,

wie fügt man richtig ein ArrayList Item hinzu, wenn diese in einer weiteren Klasse liegt?

Beispiel:
Java:
class Demo {
    private SubDemo subdemo;
}

class SubDemo {
    private ArrayList<Modul> modul;
}

class Modul {
    private String name;
}
Java:
class Main {
    private Demo demo as New Demo();
}
Wie müssen die getter/setter in der Demo und Subdemo aussehen, wenn ich diese über die class main füllen möchte?

Danke!
 
wie fügt man richtig ein ArrayList Item hinzu, wenn diese in einer weiteren Klasse liegt?
Über die weitere Klasse.

Java:
class Demo {
    private SubDemo subdemo;

    public Demo(SubDemo sub) { subdemo = sub; }
}

class SubDemo {
    private ArrayList<Modul> module;

    public void add(Modul modul) { module.add(modul); }
}

class Modul {
    private String name;
}
Java:
SubDemo sd = new SubDemo();
sd.add(new Modul());
sd.add(new Modul());
sd.add(new Modul());

Demo demo = new Demo(sd);
 
Guten Morgen,

Danke ... aber in der Demo Klasse kann ich den Konstruktor nicht nutzen, da ich mehrere solcher Verschachtelungen habe und erst irgendwann befült werden.

Ich müsste ja demnach in der Demo Klasse die Getter/Setter für die Modul Klasse erzeugen?:
Java:
class Demo {
    private SubDemo subdemo = new SubDemo();

    public void addModul(Modul modul) {
            subdemo.add(modul);
    }
}

class SubDemo {
    private ArrayList<Modul> module = new ArrayList<Modul>;

    public void addModul(Modul modul) {
        module.add(modul);
    }
}

class Modul {
    private String name;
}
Ist das so richtig?

Oder soll man die immer die komplette SubKlasse mit eimem Setter setzen? Hört sich aber nach Performance Verschwendung an, aber man würde immer über den "subdemo getter/setter" arbeiten:

Java:
class Demo {
    private SubDemo subdemo = new SubDemo();
    
    public void addModul(Modul modul) {
        SubDemo tmpSubDemo = subdemo;
        tmpSubDemo.add(modul);
        setSubdemo(tmpSubDemo);
    }
    
    public void setSubdemo(SubDemo subDemo) {
        this.subDemo = subDemo;
    }
    
}

class SubDemo {
    private ArrayList<Modul> module = new ArrayList<Modul>;
    
    public void addModul(Modul modul) {
        module.add(modul);
    }
}

class Modul {
    private String name;
}
 
Die Idee im ersten Part scheint korrekt. (Außer ein Tippfehler. Wenn die Methode addModule heisst, dann musst Du natürlich auch addModule aufrufen und nicht add.

Die Zweite Idee funktioniert technisch. Aber die Logik ist falsch: Wenn Du eine neue Liste erzeugst und da das Element hinzu fügst, dann dann wäre es kein addModul sondern eine setModule Methode. Und da nur ein Modul zu nehmen scheint auch nicht korrekt - da wäre dann evtl. ein varargs Parameter sinnvolle und dann ein Aufruf von addAll und als Parameter ein Arrays.toList Aufruf mit dem Parameter der Methode um aus dem Array eine Collection zu machen.
 
Hallo,

danke ... den Tippfehler hab ich gerade gesehen.

Das heißt aber ich muss auch neben dem "add", mindestens ein "remove" und "clear" erstellen. Und das für jedes ArrayList Element in Demo.
Bisserl aufwendig :)

Ich könnte ja die Variable "subDemo" auf Public setzen ... dann bräuchte ich gar keine Methoden, aber leider muss ich mit "PropertyChangeSupport" mich informieren lassen, wenn eine Variable geändert wird. Das geht dann ja nimmer, oder?

Konkret mit einer ArrayList als private Variable:

Java:
public class Product {
    private transient final PropertyChangeSupport pcs = new PropertyChangeSupport(this);

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        this.pcs.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        this.pcs.removePropertyChangeListener(listener);
    }
    
        private ArrayList<OtherImage> otherImages = new ArrayList<OtherImage>();
    
    
    /**
     * @return the otherImages
     */
    public ArrayList<OtherImage> getOtherImages() {
        return otherImages;
    }

    /**
     * @param the otherImages to set
     */
    public void setOtherImages(ArrayList<OtherImage> otherImages) {
        this.pcs.firePropertyChange("otherimage", this.otherImages, otherImages);
        this.otherImages = otherImages;
    }
    
    
    /**
     * @param the otherImage to add
     */
    public void addOtherImage(OtherImage otherImage) {
        this.pcs.firePropertyChange("otherimage", null, otherImage);
        this.otherImages.add(otherImage);
    }

    /**
     * @param the otherImage to remove
     */
    public void removeOtherImage(OtherImage otherImage) {
        this.pcs.firePropertyChange("otherimage", null, null);
        this.otherImages.remove(otherImage);
    }

    /**
     * clear the OtherImages
     */
    public void clearOtherImages() {
        this.pcs.firePropertyChange("otherimage", null, null);
        this.otherImages.clear();
    }
    
}
Wäre schön wenn man Eclipse sagen könnte, es soll die getter/setter so erstellen, wenn man ein ArrayList hat :cool:
 
Das heißt aber ich muss auch neben dem "add", mindestens ein "remove" und "clear" erstellen. Und das für jedes ArrayList Element in Demo.
Bisserl aufwendig :)
Also wenn Du mehrere Instanzvariablen hast, dann brauchst du mehrere von diesen "Settern/Gettern". Das ist richtig.
Welche Du aber genau brauchst hängt immer von der Logik ab. So remove und clear benötigt werden, dann ist das natürlich auch notwendig.

Ich könnte ja die Variable "subDemo" auf Public setzen ... dann bräuchte ich gar keine Methoden, aber leider muss ich mit "PropertyChangeSupport" mich informieren lassen, wenn eine Variable geändert wird. Das geht dann ja nimmer, oder?
Technisch ginge das, aber das ist ein schlechtes Design:
Implementierungsdetails sind nicht mehr gekapselt, d.h. Du kannst da nichts mehr ändern ohne auch andere Klassen anpacken zu müssen. So solltest Du Dir auch den Setter, der eine ArrayList bekommt, noch mal überlegen. Da würde ich mindestens auf List wechseln, wenn nicht auf Collection. Oder die einfache varargs Variante ...
Und dann ist es aus meiner Sicht üblich, dass man so eine Collection nicht einfach übernimmt. Statt dessen wird die ArrayList geleert oder eine neue erzeugt und dann werden alle Elemente der übergebenen Liste einmal eingefügt.
Ebenso der Getter. Der sollte dann mindestens nur eine List<...> zurück geben.
=> Du kannst dann jederzeit die Klasse ändern und statt einer ArrayList irgend was anderes verwenden. Die ArrayList sollte nach außen nie auftreten.

Ebenso sollte man sich immer überlegen, was man an Methoden braucht. Für vieles gibt es keine Getter und Setter. Du kannst ein Auto beladen und dazu dann halt den Gegenstand und Ort angeben. Also z.B. sowas wie auto.belade(sonnenbrille, HANDSCHUHFACH) aber du machst nie ein handschuhfach = new Handschuhfach(); handschuhfach.insert(Sonnenbrille); auto.setHandschuhfach(handschuhfach);, denn Handschuhfach ist ja ein Implementierungsdetail vom Auto. Das kennst Du nicht. Das ist ein Implementierungsdetail, das der Hersteller kapselt.

Daher aufpassen, was Du wo implementierst. Ein addModule das so über mehrere Klassen geht ist möglich und kann durchaus Sinn machen. Aber es "riecht" und ich würde kritisch auf das Design schauen. (Aber sehr gut möglich, dass es bei Dir eben genau so benötigt wird.)
 
Ist das so richtig?
Das ist nicht grds. falsch :) Allerdings sollte man es vermeiden, in der Klasse Objekte zu erstellen, die kein Implementierungsdetail (Collections usw.) darstellen.

Dein Product erstellt eine ArrayList, das ist in Ordnung. Dein Demo erstellt ein SubDemo - damit legst Du in Demo bereits fest, welche Implementierung von SubDemo verwendet werden soll. Nicht so gut.
 
Ebenso sollte man sich immer überlegen, was man an Methoden braucht. Für vieles gibt es keine Getter und Setter. Du kannst ein Auto beladen und dazu dann halt den Gegenstand und Ort angeben. Also z.B. sowas wie auto.belade(sonnenbrille, HANDSCHUHFACH) aber du machst nie ein handschuhfach = new Handschuhfach(); handschuhfach.insert(Sonnenbrille); auto.setHandschuhfach(handschuhfach);, denn Handschuhfach ist ja ein Implementierungsdetail vom Auto. Das kennst Du nicht. Das ist ein Implementierungsdetail, das der Hersteller kapselt.
Das würde ich noch mal unterstreichen. Ich verstehe, dass man am Anfang sehr viel Daten & Technikgetrieben ist (Ich hab ein Attribut X, auf das andere "zugreifen" sollen bzw. es bearbeiten können.

Aber in Wirklichkeit hast du in der Klasse kein Attribut X, sondern du hast eine Fachlichkeit, die die Klasse abbildet - und diese Fachlichkeit benötigt als Implementierungsdetail vielleicht ein Attribut X. Deswegen ist ein sinnvolles Vorgehen sich folgende Fragen zu stellen

* Was ist die Aufgabe meiner Klasse? Was macht meine Klasse fachlich? Was ist die Aufgabe von Product, Demo und SubDemo
* Wie soll die Klasse verwendet werden, also welche Methoden soll sie nach außen bereitstellen? Das ist unabhängig davon wie es nachher intern verwaltet wird.
* Und als letzten Schritt - wie implementiere ich die Methoden der Klasse, was für Felder von welchen Typen brauche ich um den Zustand und die Daten zu speichern.


Dann hast du vielleicht Klassen, die dienen hauptsächlich dazu um Daten zu speichern - viele Attribute, hauptsächlich get/set Methoden, wenig fachliche Methoden. Aber daneben gibt es Klassen, die rein fachliche Methoden anbieten und die gar keine get/set Methoden haben - weil du nie Daten direkt änderst, sondern irgendwas durchführen willst.

Um das Beispiel mit dem Auto aufzugreifen. Du hast vielleicht eine Klasse Tank als reine Datenklasse mit Feldern "spritArt", "volumen", "inhalt". Dafür gibt es get-Methoden für alle 3 Attribute und eine set-Methode für den Inhalt.
Und dann hast du eine Klasse Auto. Die hat innen drin ein Feld vom Typ Tank. Aber das wird gar nicht per get/set nach außen freigeben. Sondern es gibt vielleicht eine Methode tanke(int liter, SpritArt) - die dann intern das Feld tank benutzt.
 
Hallo,

danke für die guten Beispiele. Ja, eigentlich muss die erste Klasse gar nicht frei gegeben werden, da nur die Elemente darin von Bedeutung sind.
 
Passende Stellenanzeigen aus deiner Region:

Oben