Java EIN Konstruktor, der ein bis mehrere Übergabeparameter akzeptiert

Sponny

Lt. Commander
Registriert
März 2008
Beiträge
1.046
Hallo liebe Community,

ich möchte gerne EINEN Konstruktor programmieren, der bis zu 5 Übergabeparameter akzeptiert.
Also der Konstruktoraufruf soll mit 1 oder 2 oder 3 oder 4 oder sogar 5 Parametern möglich sein.

Geht das überhaupt mit einem Konstruktor oder muss man sich da immer mehrere machen?

Vielen Dank im Voraus.
 
zwei möglichkeiten:

* einige der Parameter einfach als null übergeben
* es sauber machen und für jede variante einen Konstruktor bauen der dann ggf den Konstruktor mit der nächst höheren Anzahl an Parametern aufruft.
 
Würde auch 5 Konstruktoren bauen, ist wohl die sauberste Lösung und so gibts kein Rätselraten, wenn du dir den Code in 3 Monaten wieder anguckst :)

Ansonten einen Builder nutzen, so wie es mein Vorredner vorgeschlagen hat.
 
Super, vielen Dank für die schnellen Antworten. :)
 
Falls alle Parameter den gleichen Typ haben, wäre die einfachste Lösung Varargs zu verwenden.

Code:
public Foo(Bar... bar)

Damit wäre dann allerdings auch der Aufruf völlig ohne Parameter erlaubt und müsste entsprechend behandelt werden (die bar-Variable ist ein Array, man kann also die Länge abfragen etc).

Ansonsten wie schon genannt: Builder-Pattern. Damit lässt sich besser arbeiten, als mit vielen verschiedenen Konstruktoren.
 
@soares: Das würde ich nicht einmal vorschlagen, denn ein Array suggeriert etwas ganz anderes. Eine Funktion
Code:
min(int... arguments)
würde zum Beispiel nahelegen, dass das Minimum der Werten zurückgegeben wird. Niemals würde ich erwartet, dass das als Alternative zu
Code:
min(int a, int b);
min(int a, int b, int returnIfEqual);
min(int a, int b, int returnIfEqual, int ignoreLowestN);
min(int a, int b, int returnIfEqual, int ignoreLowestN, ...);
dienen soll.
 
algernon schrieb:
@soares: Das würde ich nicht einmal vorschlagen, denn ein Array suggeriert etwas ganz anderes. Eine Funktion

Ich weiß jetzt nicht, wie man einen Konstruktur mit einer Funktion verwechseln sollte, das benötigte new erscheint mir als klare Abgrenzung.

Da der TE keine weiteren Angaben zu den Parametern gemacht hat, wollte ich diese varargs-Möglichkeit zumindest mal nennen, auch wenn ich persönlich (fast immer) das Builder-Pattern präferieren würde.

algernon schrieb:
Code:
min(int... arguments)
würde zum Beispiel nahelegen, dass das Minimum der Werten zurückgegeben wird. Niemals würde ich erwartet, dass das als Alternative zu
Code:
min(int a, int b);
min(int a, int b, int returnIfEqual);
min(int a, int b, int returnIfEqual, int ignoreLowestN);
min(int a, int b, int returnIfEqual, int ignoreLowestN, ...);
dienen soll.

Eine solche Alternative bereitzustellen würde auch wenig Sinn machen, trifft den besagten Fall aber auch nicht. Hier ging es darum einen Konstruktur zu erstellen. Da hätte man keine Alternative und mithin auch keine Verwirrung.

Wobei es durchaus Fälle geben kann, in denen eine Funktion mit einem Varargs-Parameter neben anderen stehen kann, ohne verwirrend zu sein wie z.B. bei der of() Methode des EnumSets zu sehen (hier sieht man auch eine Möglichkeit mindestens einen Parameter zu erzwingen).

Es kommt halt immer auf den Anwendungsfall an. Der TE hat hierzu keine näheren Angaben gemacht.
 
So, hier ist mal meine "unsaubere" Lösung die zwar funktioniert. Ich möchte es aber natürlich sauber machen...

Bei Resource handelt es sich auch um eine Enum.

Ich möchte das der Konstruktor eine beliebige Anzahl von diesen Enum-Werten akzeptiert, also auch mehr als 5.

Für Tipps oder Lösungen bin ich sehr dankbar.

Code:
public enum Things {

	Thing(1, Resource.A, Resource.B, null, null, null), 
	Thing1(3, Resource.C, Resource.D, Resource.B, Resource.A, null), 
	Thing2(2, Resource.C, Resource.D, Resource.Stone, null, null), 
	Thing3(5, Resource.D, Resource.D, Resource.E, Resource.E,Resource.E);

	private final int[] resources = new int[Resource.NUMRESOURCES];
	private final int points;
	
	private Things(int points, Resource a, Resource b, Resource c,
			Resource d, Resource e) {
		this.points = points;
		if (a != null) {
			resources[a.ordinal()]++;
		}
		if (b != null) {
			resources[b.ordinal()]++;
		}
		if (c != null) {
			resources[c.ordinal()]++;
		}
		if (d != null) {
			resources[d.ordinal()]++;
		}
		if (e != null) {
			resources[e.ordinal()]++;
		}
	}
}
 
Na, da passt ein Konstruktur mit Varargs-Parameter doch wie Arsch auf Eimer!

Das resources-Array wird dynamisch erstellt. Die Ordinal-Werte in einer Schleife kopiert. Was benötigst Du hier noch an Tipps?
 
So, hier mal die Lösung wie ich es gemacht habe:

Code:
public enum Things {
 
	Thing(1, Resource.A, Resource.B), 
	Thing1(3, Resource.C, Resource.D, Resource.B, Resource.A), 
	Thing2(2, Resource.C, Resource.D, Resource.Stone), 
	Thing3(5, Resource.D, Resource.D, Resource.E, Resource.E,Resource.E);
 
	private final int[] resources = new int[Resource.NUMRESOURCES];
	private final int points;

        private Things(int points, Resource... b) {
		this.points = points;
		for (int i = 0; i < b.length; i++) {
			resources[b[i].ordinal()]++;
		}
	}
}
 
Das "resources"-Array würde ich dynamisch erstellen. Die maximale Größe ist ja für jede Konstante anders. Spart jetzt nicht irre viel Speicher, aber man so hätte man auch keine Kopplung mit "Resource".

Sind die Werte für das "points"-Feld korrekt? Bei den ersten drei Konstanten ist der Wert um eins kleiner, als die Anzahl der Parameter. Beim letzten ist er gleich? Falls er immer um eins kleiner sein sollte, würde ich den "points"-Parameter weglassen und den Wert über das Array bestimmen. Vermeidet Mühe und Fehler ;)

Die Schleife verstehe ich nicht. Hast Du überprüft, dass im "resources"-Array am Ende die korrekten Werte stehen?

Wozu wird die Klasse eigentlich verwendet? Losgelöst erscheint das ganze wenig sinnvoll.
 
Zurück
Oben