ArrayList auf 4 Elemente begrenzen

lubi27X

Aktives Mitglied
Java:
import java.util.ArrayList;

public class CategoryOverview {

    //catList with all categories; maximal 10 Elemente
    ArrayList<Category> catList = new ArrayList<Category>(4);

    
    //Konstruktor
    CategoryOverview(Category...category) {
        
        for(int i = 0; i < category.length; i++)
        {
            this.catList.add(category[i]);
        }

Java:
    public static void main(String[] args) {
        
                CategoryOverview categoryList = new CategoryOverview(food,transfer,rent,electric,salary,present);


In der Klasse CategoryOverview habe ich eine ArrayList, die Categorien aufhnehmen kann. Jedoch möchte ich die maximale Anzahl an Elementen auf 4 beschränken. Das habe ich nun auch in Zeile 6 gemacht.
In meiner Main Methode übergebe ich der Referenzvariable 6 Categorien. Eigenltich hätte ich jetzt gehofft, dass eine Fehlermeldung angezeigt wird, weil die maximal Anzahl, die die ArrayList aufnehmen kann auf 4 beschränkt ist, ich jedoch 6 übergebe.
Kann mir jeman sagen woran das liegt?
 
Nein, bei dem Parameter handelt es sich um die initiale Groesze des internen Speichers der "ArrayList", aber selbst der ist nur ein Richtwert und muss nicht zwingend von der Implementation direkt uebernommen werden, wenn ich es richtig im Kopf habe.

Du musst hier eine Pruefung einbauen wenn du die Elemente in die Liste aufnimmst, ob schon zu viele Elemente in der Liste sind oder nicht. Ich kenne hier keine vorgefertigte Klasse welche das einfach einschraenken wuerde.
 
und muss nicht zwingend von der Implementation direkt uebernommen werden, wenn ich es richtig im Kopf habe
der wird schon "übernommen", ist aber wie gesagt zur Programmlauzeit variabel, d. h. es dürfen weniger oder mehr Elemente aufgenommen werden.

@E27T Schreib dir eine eigene Klasse, die die ArrayList "wrappt". D. h. wenn bei einer Hinzufügemethode voll ist, ist voll, dann kannst du false zurückgeben oder einen Fehler erstellen, und darauf reagieren. Kannst du das?
 
Java:
import java.util.ArrayList;

public class CategoryOverview {

    //catList with all categories; maximal 10 Elemente
    ArrayList<Category> catList = new ArrayList<Category>();

    
    //Konstruktor
    CategoryOverview(Category...category) {
        
        for(int i = 0; i < category.length; i++)
        {
            if (category.length < 6)
            {
                this.catList.add(category[i]);
                
            }
            else
            {
                System.out.println("Maximal 6 Kategorien");
                break;
            }
        }

Ich habe das jetzt so gemacht. Ist aber auch blöd. Der soll mir am besten in der Main Methode, wenn ich die Objekte "Categorie" übergebe, direkt melden, wenn ich zu viele übergebe.
 
Also ich finde es schon interessant:
- Subject besagt 4 Element ("ArrayList auf 4 Elemente begrenzen")
- Kommentar vor der Instanzvariable spricht von 10 Elementen ("//catList with all categories; maximal 10 Elemente")
- Im Konstruktor prüfst Du auf <6 Element ("category.length < 6")

Ansonsten hast Du ja schon eine Klasse CategoryOverview, daher weisst Du ja schon, wie Du so eine Klasse schreiben kannst. Die eigene Klasse würde prinzipiell ähnlich aussehen. Du hättest eine entsprechende Instanzvariable und dann würdest Du die Methoden zur Verfügung stellen, die Du brauchst, also z.B. eine add Methode...
 
Also ich finde es schon interessant:
- Subject besagt 4 Element ("ArrayList auf 4 Elemente begrenzen")
- Kommentar vor der Instanzvariable spricht von 10 Elementen ("//catList with all categories; maximal 10 Elemente")
- Im Konstruktor prüfst Du auf <6 Element ("category.length < 6")
Habe vergessen die Zahlen überall anzupassen. Es geht mir aber um das Prinzip, wie man das macht. Es ist generell egal, ob ich auf 4, 6 oder 10 prüfe. Mir stellt sich nur die Frage, wie ich ein ArrayList "begrenzen" kann.
 
Ansonsten hast Du ja schon eine Klasse CategoryOverview, daher weisst Du ja schon, wie Du so eine Klasse schreiben kannst. Die eigene Klasse würde prinzipiell ähnlich aussehen. Du hättest eine entsprechende Instanzvariable und dann würdest Du die Methoden zur Verfügung stellen, die Du brauchst, also z.B. eine add Methode...
Werde daraus nicht schlau. Eine ArrayList bietet mir doch schon eine add() Methode. Wozu selber noch eine schreiben?
 
Werde daraus nicht schlau. Eine ArrayList bietet mir doch schon eine add() Methode. Wozu selber noch eine schreiben?
Weil die add-Methode der ArrayList ja offensichtlich nicht reicht 🙂

Was du willst ist eben keine Standard-Liste, sondern etwas eigenes – also ist es sinnvoll, etwas eigenes zu schreiben (was dann intern eine ArrayList nutzt).
 
Und das Interessante war halt, dass Du sehr schön demonstriert hast, wieso so Kommentare nicht gut sind.

Damit kommen wir aber etwas vom eigentlichen Thema weg. Aber ich nutze hier die Stelle einfach einmal kurz, das zu erläutern.

Code lebt, d.h. durch ständige Wartung und Weiterentwicklung verändert er sich. Daher ist es immer schlecht, wenn eine Änderung an einer Stelle auch eine Änderung an einer anderen Stelle erfordert und dies nicht zu einem Fehler führt, wenn dies vergessen wird. Dies ist hier offensichtlich der Fall.

Daher gehört sowas nicht in den Code! Daher sollte Code so geschrieben sein, dass er sich selbst erklärt. Dies kann durch gute Bezeichner erfolgen. Und dann sollten auch "magic numbers" vermieden werden. Also so eine 6 ist ganz schlecht. Wer weiss, an wie vielen Stellen nun eine solche 6 vorkommt? Und wenn es nun 10 werden sollen, dann gehst Du den ganzen Code durch und musst es an vielen Stellen anpassen. Aber evtl. gibt es auch noch andere 6er im Code, die Du nun natürlich nicht zu einer 10 ändern darfst.

Daher wäre hier z.B. eine Konstante wichtig:
public static final int MAX_NUMBER_OF_CATEGORIES = 6;
Und diese Konstante verwendest Du dann immer, wo Du dies brauchst.

Das musst Du auch nicht kommentieren - oder willst Du da noch einen Kommentar drüber schreiben: "max number of categories is 6."?
 
@E27T Ggfs public void add(int index, E element) { auch noch überschreiben ...

Java:
import java.util.ArrayList;

public class MyAL<T> extends ArrayList<T> {
    private static final long serialVersionUID = 1L;
    private final int max_capacity;

    public MyAL(int max_capacity) {
        this.max_capacity = max_capacity;
    }

    @Override
    public boolean add(T e) {
        if (this.size() < max_capacity) {
            return super.add(e);
        }
        return false;
    }

    public static void main(String[] args) {
        MyAL<Integer> ali = new MyAL<>(4);
        ali.add(6);
        ali.add(5);
        ali.add(4);
        ali.add(3);
        ali.add(2);
        System.out.println(ali);
    }
}
 
Also bezüglich der Lösungsidee von @123neu:
a) Bei Bezeichnern auf die Java Naming Conventions achten und generell sinnvolle Namen vergeben.

b) Ich würde auf keinen Fall ableiten!
Zum einen: Wenn man ableitet, dann die Klasse, von der man ableitet, im Detail betrachten und sicher stellen, dass man an alles gedacht hat! Es fällt z.B. direkt die addAll Methode ins Auge ....Aber so muss man halt im Detail prüfen, was man alles übernimmt.
Zum Anderen: Wir haben einen Contract, der erfüllt sein muss. So ist der Contract von Collection.add(E) nicht erfüllt:
If a collection refuses to add a particular element for any reason other than that it already contains the element, it must throw an exception (rather than returning false).

Daher ist es am einfachsten, eine eigene Klasse zu schreiben, eine ArrayList als Instanzvariable und dann die Methoden, die man braucht, dazu zu nehmen....
 
das hab ich doch anfangs vorgeschlagen... aber so ist es erst einmal einfacher...
Nein, so ist es nicht einfacher sondern aus meiner Sicht schlicht falsch. Denn diese Lösung macht nicht das, was von ihr erwartet wird ...
Nö. Sieh dir mal die add Methode von ArrayList an, dieser "Kontrakt" ist Murks.
Genau das solltest Du einmal machen. Denn genau da findest Du auch den Hinweis auf Collection.add(E):

Das mag richtig sein. Aber spätestens, wenn ich einen Iterator benutzen will, artet dies zu Arbeit aus.
Da ist die Frage, was die Anforderung genau ist. Die einzige Anforderung ist bisher, dass es ein add(Category) unterstützen muss.
Und wirklich Arbeit sehe ich nicht - denn man kann ja (ähnlich wie von @mrBrown schon vorgeschlagen) auf die Möglichkeiten der verwendeten ArrayList zugreifen. Eine Implementation von iterator() ist dann einfach eine Rückgabe des iterator() Aufrufs von der internen ArrayList....

Und ja - dann lieber etwas mehr Tipparbeit (incl den Unit Tests) und damit dann eine Lösung, die sich korrekt verhält. Das bevorzuge ich gegenüber "schnellen Lösungen" mit angeblich "weniger Arbeit" die dann Nebeneffekte mit sich bringen. Die Erfahrung zeigt leider, dass genau so Nebeneffekte dann später deutlich mehr Arbeit mit sich bringen können.

Edit: Beim ersten Satz fehlten irgendwie paar Worte ...
 
doch leider verstehe ich von dem Code nicht so viel
Neben aller Diskussion, ob es sinnvoll ist, von ArrayList zu erben:

In dem Beispiel MyAL wird von java.util.ArrayList geerbt.
Der Konstrunktor bekommt die maximale Anzahl von Elementen mitgegeben (und merkt sie sich).
Die Methode add überprüft, ob bereits zu viele Elemente hinzugefügt wurden. Er gibt zur Zeit false zurück, falls schon zu viele Elemente hinzugefügt wurden (dies könnte man verbessern, indem stattdessen eine Exception geworfen wird - wie im "Contract" gefordert).
Die main-Methode dient nur zum Testen.
 
A) wer sagt, dass dieser Kontrakt auch in einer die Liste verändernden Klasse gelten muss? Sinn ist doch gerade, ein anderes Verhalten.
B) ich habe mich bewusst gegen eine Ausnahme entschieden (denn Ausnahmen sollten nicht das Programm steuern...)
 
A) wer sagt, dass dieser Kontrakt auch in einer die Liste verändernden Klasse gelten muss? Sinn ist doch gerade, ein anderes Verhalten.
Der Kontrakt steht in einem Interface! Jede implementierende Klasse muss ihn erfüllen.
B) ich habe mich bewusst gegen eine Ausnahme entschieden (denn Ausnahmen sollten nicht das Programm steuern...)
Der Aufrufer hat ja selber die Möglichkeit, zu überprüfen, ob deine MyAL schon "voll" ist (zumindestens, wenn die eine Methode getMaxCapacity() anbietest). Deshalb ist eine RuntimeException keine schlechte Wahl.
 
A) Es gibt so Ideen wie Clean Code. Da gehören dann auch so komische Dinge wie das Liskovsches Substitutionsprinzip:
Davon muss man nichts halten aber die praktische Erfahrungen der letzten Jahre zeigen, dass es durchaus Sinn macht.

B) Du steuerst dadurch ja nicht den Programmfluss. Das ist so, wie wenn der Entwickler eine NPE bekommt: wenn du hier eine Exception bekommst, dann hast du etwas falsch gemacht.
Hier im konkreten Fall hast du beim Einfügen nicht auf die Boundaries geachtet.
 
Ehm, ich wollte eine schnelle, einfache, pragmatische Lösung... Alternativen habe ich auch genannt, deswegen verstehe ich die Aufregung nicht so ganz oder, warum die Lösung nicht gut sein soll. Wenn man AL nicht überschreiben hätte können sollen, so hätte man sie auch final machen können... hat man aber nicht, eben weil hier nur ein Teil der Funktionalität verändert werden soll... jm2c.
 
Es regt sich niemand auf und das Warum ist erläutert worden. Und natürlich sind Fälle denkbar, in denen man von ArrayList ableiten kann ohne dass es so Punkte gibt, die dann 'angemeckert' werden.

Wenn du Beispiele suchst, dann könnte man z.B. die Direct Known Subclasses anschauen. Und alleine schon der Fakt, dass es diese gibt, zeigt doch, wieso die Klasse nicht final gemacht wurde.

Wenn du einzelne Argumente nicht verstehst, dann könntest du dazu auch gerne einen separaten Thread zu erstellen. Dann könnte man diese noch im Detail erläutern. Das mit den Interfaces ist z.B. schnell einleuchtend, wenn man Empfehlungen betrachtet wie 'Gegen Interfaces entwickeln'. Aber das hier weiter auszuführen ist OT und daher vertiefe ich es nicht weiter. (@mrBoder kopierst du ab einer Stelle in einen neuen Thread? Kopieren statt verschieben ist evtl. teilweise angebracht, denn die Lösungsidee + erste Bewertung gehört hier ja durchaus rein...) Eine Erläuterung könnte für den einen oder Anderen, der über diesen Thread kommt, ja durchaus interessant sein.
 
Wenn es wirklich immer nur 4 Elemente sind, ist auch über ein simples Array nachzudenken.
Ja da hast du recht, wir als Team haben uns für diese Aufgabe aber für eine ArrayList entschieden.

Ich würde die Anforderungen an das Programm gerne noch etwas ändern.
Java:
        Category food = new Category("Nahrungsmittel");
        Category rent = new Category("Miete");
        Category salary = new Category("Gehalt");
        Category present = new Category ("Geschenke");
        Category electric = new Category ("Elektronik");
        Category transfer = new Category ("Umbuchung");
        Category shopping = new Category ("Shoppen");

Hier erzeuge ich die neuen Kategorien.

Wie bekomme ich das hin, dass die Kategorien "automatisch" der categoryList hinzugefügt werden, ohne das ich die der Liste übergeben muss, so wie es gestern der Fall sein sollte.
Java:
//Erzeugt neue categoryList und übergibt Categorys
CategoryOverview categoryList = new CategoryOverview(food,transfer,rent,electric,salary,present);

Versteht ihr was ich meine? Sobald ich bspw. "rent" erzeuge, soll "rent" der categoryList hinzugefügt werden.. Die categoryList soll quasi von den Categories leben.
 
Die frage ist erst einmal, was ihr alles genau vor habt. Denn davon hängt schlicht das Design ab.

Eine übliche Sache ist, dass man hier eine normale Datenhaltung hat:
- Die Daten kommen dann aus irgend einer Quelle (z.B. einer Datei, Datenbank, Webservice, ....)
- Man hat eine Klasse (Entity oder Data Transfer Object (DTO) genannt), die einen Datensatz aufnehmen kann.
- Man hat eine (mindestens eine) Klasse die dann für das Laden / Speichern / Suchen und so verantwortlich ist (Repository oder Data Access Object (DAO) genannt). Hier dann kurz am Rande: Es gibt dann Frameworks / Libraries, die das extrem automatisieren. Es wird dann teilweise nur noch ein Interface geschrieben und die konkrete Implementation wird dann automatisch generiert ... Das kann also am Ende mit entsprechenden Libraries sehr einfach aussehen mit sehr wenig Aufwand.

Etwas in der Art ist bei Dir natürlich auch denkbar:
Du hast dann eine Klasse a.la. CategoryRepository mit getCategories() das einfach eine List<Category> zurück gibt.
(CategoryOverview würde es dann auch vermutlich nicht mehr geben... oder das wird dann diese Methode)

Und diese getCategories() könnte einfach eine Liste von Categories laden, z.B, aus einer Resource Datei. Also einfach per getClass().getResourceAsStream("/categories.txt") die Resource-Datei öffnen und dann Zeile für Zeile lesen. Für jede Zeile wird der Konstruktor aufgerufen und die Instanz kommt in eine ArrayList<Category>. Am Ende wird die Anzahl noch validiert (Also z.B. mind. 1 Category muss existieren und maximal die bestimmte Anzahl ...)
Dann hättest Du eine feste Anzahl an Kategorien die dann nicht verändert wird. (Also ähnlich wie das fixe Anlegen bei Dir im Code - nur eben vom Code separiert. Und Du hast eine zentrale Klasse mit der Logik, d.h. Du kannst in dieser Klasse jederzeit anpassen, woher die Daten kommen und Du kannst weitere Methoden hinzufügen und so ...)

Das wäre so ein Aufbau, wie er heutzutage das ist, was ich als "üblich" ansehen würde und das man immer wieder findet in diversen Varianten.


Eine weitere Idee könnte sein, dass man Category Instanzen so gar nicht anlegt. Statt dessen wird eine sogenannte Factory-Methode verwendet. Das könnte dann also sein, dass CategoryOverview eine createCategory Methode hat. Dann würde der Aufruf lauten:
Category food = categoryOveriew.createCategory("Nahrungsmittel");


Natürlich ist rein technisch auch ein anderer Aufbau denkbar. Das ist aber jetzt eine Lösungsidee, die ich explizit nicht empfehle sondern auch davon abrate!
So könnte die Klasse Category eine Klassenvariable haben:
private static final List<CategoryList> categories = new ArrayList<>();

Im Konstruktor kannst Du dann jede Instanz dort hinzufügen. Wenn die maximale Anzahl überschritten ist, kannst Du eine Exception werfen. Und die List kannst Du Dir dann natürlich auch über ein Getter oder so geben lassen.
Aber so static Elemente sollten - soweit möglich - vermieden werden.
 
Später soll alles über eine GUI laufen und die Eingaben erfolgen mittels Input- und Outputstream.
Eine weitere Idee könnte sein, dass man Category Instanzen so gar nicht anlegt. Statt dessen wird eine sogenannte Factory-Methode verwendet. Das könnte dann also sein, dass CategoryOverview eine createCategory Methode hat. Dann würde der Aufruf lauten:
Category food = categoryOveriew.createCategory("Nahrungsmittel");

Das hört sich für mich irgendwie am sinnvollsten an. In der CategoryOverview Klasse gibt es quasi eine Methode, die eine neue Category erzeugt und sie an die Liste anfügt. Verstehe ich das so richtig?
 
Später soll alles über eine GUI laufen und die Eingaben erfolgen mittels Input- und Outputstream.
Also das verstehe ich jetzt so nicht. Streams hört sich etwas nach Dateien an und da würde dann die Idee mit dem Repository passen.
GUI selbst kommt in der Regel ohne Streams aus. Da wird dann mit Controls gearbeitet, denen man dann die entsprechenden Werte direkt entnehmen kann.

Aber so ihr da eine genaue Vorstellung habt, dann macht erst einmal in Ruhe weiter. Wenn ihr auf Probleme stoßt, dann weißt Du ja, wo Du mach Hilfe fragen kannst. Der Punkt ist vermutlich einfach nur eine Frage der verwendeten Begriffe und muss erst einmal nichts bedeuten - daher kein Grund, das zu vertiefen.
Das hört sich für mich irgendwie am sinnvollsten an. In der CategoryOverview Klasse gibt es quasi eine Methode, die eine neue Category erzeugt und sie an die Liste anfügt. Verstehe ich das so richtig?
Ja, das hast Du richtig verstanden.
 
Category food = categoryOveriew.createCategory("Nahrungsmittel");
Da scheitert es bei mir schin hieran. Warum schreibst du "... = catgoryOverview.createCategory("Nahrungsmittel")?
Java:
Category work = categoryList.createCategory("work");

Ich hätte das jetzt so gemacht, es kommt aber eine Fehlermeldung 1618296259054.png

Ich greife doch über die categoryList auf die Methode "createCategory" zu.
 
Wie sieht denn deine Methode createCategory aus? Ich würde jetzt auf Grund der Fehlermeldung behaupten, dass Du als Rückgabetyp void hast:

Java:
public void createCategory(final String categoryName) {
    Categegory category = new Category(categoryName);
    this.add(category);
}

Das soll aber die neue Category zurück geben, also so:
Java:
public Category createCategory(final String categoryName) {
    Categegory category = new Category(categoryName);
    this.add(category);
    return category;
}

Das einfach einmal auf die Schnelle im Forum geschrieben - Tippfehler also bitte ignorieren. Aber es sollte erkenntlich sein, was ggf. geändert werden muss:
a) Category als Rückgabetyp.
b) return mit der neu erstellten Category.
 
Das final bedeutet, dass Du dem Parameter categoryName, der ja eine lokale Variable in der Methode darstellt, nichts zuweisen kannst. Das final bedeutet im Allgemeinen nicht, dass Du das Objekt selbst nicht ändern kannst. Das ist hier nur "zufällig" der Fall, da der Typ String unveränderlich ist.
 
Ich frage halt, weil es auch ohne "final" funktioniert
Das final ist einfach ein zusätzlicher Schutz, dass man dem Parameter nicht versehentlich etwas zuweist. An der Funktion ändert final nichts.

Beispielsweise soll man eine Variable nur für einen Zweck verwenden. Wenn Du also einen Parameter hast, dann soll der nur als Parameter herhalten und nicht in der Methode für was anderes verwendet werden. So etwas kannst Du per final sicherstellen.
 
Ich frage halt, weil es auch ohne "final" funktioniert
Ja, das geht auch ohne da final.

Ob man da ein final setzt oder nicht darf sich jeder selbst überlegen. Ich selbst halte es für eine Art Best Practice, dass man Dinge, die man nicht verändern möchte / sollte, final zu machen. Wenn man statische Codeanalysetools wie PMD verwendet, dann gibt es da oft auch entsprechende Regeln wie bei PMD das MethodArgumentCouldBeFinal.

Eine Begründung, wieso ich das so mache, muss ich nicht mehr nennen - da ist mir @mihe7 zuvor gekommen 🙂
 
@kneitzel , danke für den Tipp, mit der Factory-Methode. Das sieht auf jeden Fall etwas schlanker aus.
Würde trotzdem gerne nochmal den Punkt aufgreifen, um irgendwie die Anzahl der Kategorien auf eine Zahl (sagen wir 5) zu begrenzen. Der Benutzer darf also maximal 5 Kategorien anlegen. Meine Klasse CategorieOverview sieht jetzt so aus...
Java:
import java.util.ArrayList;

public class CategoryOverview {

    //catList with all categories
    ArrayList<Category> catList = new ArrayList<Category>();
    
    int maxAnzahlCategorie = 4;

    
    //Konstruktor
    CategoryOverview(Category...category) {
        
        for(int i = 0; i < category.length; i++)
        {
            if (category.length <= 4)
            {
                this.catList.add(category[i]);
                
            }
            else
            {
                System.out.println("Maximal 4 Kategorien");
                break;
            }
        }
    }
    //method creates new categories
    public Category createCategory(String categoryName) {
        
        Category category = new Category(categoryName);
        
        this.catList.add(category);
        return category;
    }
    
    
    //shows all payments
    public void showCatList() {
        
        for(Category n: catList)
        {
            n.showCatPaymentList();
//            System.out.println(n.getName() + n.getCatPaymentList().toString());   
        }
    }
}

Den Konstruktor in Zeile 12 und die if-Abfrage kann ich mir ja jetzt eigentlich sparen, da ich in dies ja in der Methode createCategory machen muss.. Würde mich freuen, wenn man mir einfache Tipps geben würde....Die Lösung von gestern mit der neuen Klasse fand ich bisschen zu "heftig" auch wenn man es als Programmierer vielleicht in der echten Welt so macht.
 
Würde trotzdem gerne nochmal den Punkt aufgreifen, um irgendwie die Anzahl der Kategorien auf eine Zahl (sagen wir 5) zu begrenzen. Der Benutzer darf also maximal 5 Kategorien anlegen.
Du kannst einfach in createCategory prüfen, ob noch eine weitere angelegt werden darf, und in dem Fall entweder mit Fehler oder mit null als Return-Wert die Methodenausführung beenden.

Die Lösung von gestern mit der neuen Klasse fand ich bisschen zu "heftig" auch wenn man es als Programmierer vielleicht in der echten Welt so macht.
Deine Lösung ist genau so eine Lösung mit neuer Klasse 😉
 
Mir ist nicht so ganz klar warum meine Methode createCategory() einen Datentyp Category zurückgibt und nicht void?
Wozu muss ich die category "returnen"?
Ich will doch nur, dass eine neu Kategorie meiner ArrayList catList hinzugefügt wird?
 
Du kannst einfach in createCategory prüfen, ob noch eine weitere angelegt werden darf, und in dem Fall entweder mit Fehler oder mit null als Return-Wert die Methodenausführung beenden.
Java:
//method creates new categories
    public Category createCategory(String categoryName) {
        
        Category category = new Category(categoryName);
        
        if (catList.size() <= 5)
        {
            this.catList.add(category);
        }
        else
        {
            System.out.println("Die maximal Anzahl an Kategorien ist erreicht!");
        }
        return category;
    }

macht das so Sinn?
 
macht das so Sinn?
Jein – der Programmierer hat ja jetzt keine Möglichkeit um zu überprüfen, ob die Category hinzugefügt wurde, das sieht man ja nur, wenn man während der Laufzeit zufällig aus die Konsolenausgabe schaut 🙂

Besser ist es, eine Exception zu schmeißen (wenn man die Möglichkeit bietet, vorher abzufragen, wie viele Kategorien schon enthalten sind) oder null (alternativ Optional) zurückzugeben. Dann kann der Programmierer entscheiden, ob das in dem Moment auf der Konsole ausgegeben werden muss oder woanders.
 
Könntest du mir diese Frage auch noch beantworten. Ist für mich ein entscheidender Punkt
Also eine Factory Methode erstellt einen Wert und gibt diesen zurück. createCategory sollte daher eine Categoy zurück geben. Aber das musst Du ncht zwangsweise so handhaben. Du kannst das auch gerne anders handhaben und nichts zurück geben. Aber dann evtl. noch einen besseren Namen wählen.... createCategory klingt für mich halt nach erzeugen und zurück geben ...

Und bezüglich deines Codes:
Java:
//method creates new categories
    public Category createCategory(String categoryName) {
       
        Category category = new Category(categoryName);
       
        if (catList.size() <= 5)
        {
            this.catList.add(category);
        }
        else
        {
            System.out.println("Die maximal Anzahl an Kategorien ist erreicht!");
        }
        return category;
    }

macht das so Sinn?
Da ist dann eine RuntimeException zu werfen statt einer Ausgabe. Also einfach "System.out.println" durch "throw new RuntimeException" ersetzen.

Hintergrund ist, dass da der Entwickler nicht aufgepasst hat und noch eine Category erzeugen wollte obwohl dies nicht möglich ist.

Evtl. noch die Prüfung in eine eigene Methode: canCreateAnotherCategory() oder so. Dann hat der Entwickler vor dem Erzeugen auch eine Prüfmöglichkeit,
 
Die Factory Methode gibt dies an den Aufrufer zurück. Ob und was der damit macht bleibt dem Aufrufer überlassen. Prinzipiell muss er damit nichts machen.

Aber ebenso musst Du nicht zwingend an dem beschriebenen Pattern festhalten. Wenn Du da diese Rückgabe nicht brauchst, dann mach die Methode zu einer void Methode und gib nichts zurück. Technisch ist das kein Problem. Nur wie gesagt: Du kannst darüber nachdenken, ob Du evtl. dann einen besseren Namen findest - zumindest ich würde bei einer createXXX Methode erwarten, dass ich ein XXX zurück bekommen würde. Aber ich möchte nicht einmal ausschließen, dass Andere eine andere Erwartungshaltung haben.
 
Und wenn ich die Methode auf void setze, zeigt sie zwar keine Fehlermeldung an, dafür aber die Main Methode..
Java:
//method creates new categories
    public void createCategory(String categoryName) {
        
        Category category = new Category(categoryName);
        
        if (catList.size() <= maxAnzahlCategorie)
        {
            this.catList.add(category);
            System.out.println("Kategorie " + categoryName +" wurde hinzugefügt");
        }
        else
        {
            System.out.println("Die maximale Anzahl an Kategorien ist erreicht");
        }
//        return category;
    }

1618312196240.png
 
Da musst Du natürlich auch die main Methode ändern. Da Du nichts zurück bekommst, kannst Du die angelegten Category nicht mehr in lokalen Variablen speichern.
 

Zurück
Oben