Java Abstrakte Methode mit undefiniertem Übergabewert (Variabletyp)

Fleshgrinder

Lt. Junior Grade
Registriert
Mai 2005
Beiträge
405
Ich konnte zu dieser Frage leider keine befriedigende Antwort via Google finden.

Prinzipiell ist es ja gut, dass Java halbwegs typensicher ist, doch manchmal nervt es mich dann doch sehr. Folgende Ausgangssituation, ich will das FactoryPattern für ein Package umsetzen und habe eine Basisklasse von der alle ableiten und die nach außen sichtbar ist. Ich verwende kein Interface weil ich einige Methoden bereits ausprogrammiert haben möchte. Keine Ahnung ob das entgegen dem FactoyPattern ist.

Ok, nun zu meiner eigentlichen Frage. Da nach außen nur diese abstrakte Klasse sichtbar ist, kann ich auch nur auf die Methoden zugreifen, die dort definiert sind. Nun will ich aber bei verschiedenen Unterklassen verschiedene Properties setzen können und brauche deshalb eine allgemeingültige Funktion dafür. Ich habe dabei an etwas gedacht wie.

Code:
public abstract class Mama {
	/**
	 * Generic property setter.
	 */
	public abstract void setProperty(String property, <?> value);
}

PHP:
class Kind1 {
	// {{{ Properties
	private String property1;
	private String property2;
	private int property3;
	// }}}

	public void setProperty(String property, String value) {
		if (property.equalsIgnoreCase("property1")
			property1 = value;
		else if (property.equalsIgnoreCase("property2")
			property2 = value;
	}

	public void setProperty(String property, int value) {
		property3 = value;
	}
}

Bezüglich der ersten setProperty() Methode noch eine Anmerkung. Mir wäre nicht bekannt, dass es in Java etwas wie in PHP gibt, wo von einem String auf eine Variable geschlossen werden kann. Wenn ich mich recht entsinne ging das in PHP irgendwie so:

PHP:
$property = NULL;

$string = "property";

${$string} = "value";

echo $property; // Liefert value

Java kann das natürlich nicht. :rolleyes:

Ich hoffe ihr versteht was ich erreichen will, sonst einfach Löcher in den Bauch fragen. :p
 
Zuletzt bearbeitet:
Mir ist auch nichts bekannt, das dieser PHP-Trick funktioniert, wäre aber ohnehin unsauber, da die Variablennamen innerhalb und außerhalb der Klasse gleich sein müssen, damit das ordnungsgemäß funktioniert. Wenn du nun also an der Klasse rumschraubst, müsstest du unter Umständen deine Programme anpassen, die die Klasse verwenden.
Stattdessen könntest du einfach mit dem Object-Datentyp arbeiten. Damit fallen natürlich die primitiven Datentypen wie int, double oder boolean weg, aber dafür gibt es ja von Java auch bereitgestellte Klassen wie Integer, Double oder Boolean, die alle von der Object-Klasse abgeleitet sind.
Bei der Implementierung der setProperty-Methode musst du dann natürlich abhängig vom übergebenen String noch richtig casten, aber das versteht sich dann von selbst.
 
Zuletzt bearbeitet:
Dies ist mir so auch schon durch den Kopf gegangen, nur die viele Schreibarbeit und das Casten haben mich abgeschreckt.

PHP:
class Kind extends Mama {
	// {{{ Properties
	private int property1;
	// }}}

	public void setProperty(String property, Object value) {
		if (property.equalsIgnoreCase("property1") && GenericValidator.isInt(value))
			property1 = (int) value;
	}
}

So müsste das dann aussehen (GenericValidator). Die primitiven Typen fallen eigentlich nicht einmal weg, da es für jeden primitiven Typ auch einen Wrapper gibt (int = Integer, double = Double, usw.).

Ach und bezüglich PHP und unsauber, das was ich erreichen will wäre mit PHP sehr einfach.

PHP:
class Kind extends Mama {
	public setProperty($property, $value) {
		if (isset($this->{$property}))
			$this->{$property} = $value;
	}

	public getProperty($property) {
		if (isset($this->{$property}))
			return $this->{$property};
		return NULL;
	}
}

Die Variable in der aufrufenden Klasse kann dann heißen wie sie will und der Wert der Variable kann jeden beliebigen Typ haben, da PHP das sowieso selbst erledigt.

PHP:
$myVariable = "value";

$kind = new Kind();

$kind->setProperty("property1", $myVariable);

$myVariable = $kind->getProperty("property1");
 
Zuletzt bearbeitet:
Prinzipiell hab ich mir das so vorgestellt, allerdings ist der GenericValidator meiner Meinung hier nicht sehr sinnvoll. Der checkt lediglich, ob ein String sinnvoll in einen Int-Wert umgewandelt werden kann, was du ja eigentlich garnicht machen willst. Dafür gibt es den instanceof-Operator, der überprüft ob ein Objekt eine Instanz einer Klasse ist (wenn dem so ist, kannst du einfach casten).
Du hast recht, Integere nach int sollte Problemlos funktionieren, selbst das casten müsste man sich schenken können, wird ja implizit gemacht, allerdings schadet es auch nicht.
Mir ist klar, wie das in PHP funktioniert. In deiner PHP-Implementierung müssen allerdings dann wie gesagt deine Attribute genauso heißen, wie der String, den du übergibst. Das ist zwar eine schnelle Lösung und spart Tipparbeit, aber meiner Meinung ist das auch in PHP keine sinnvolle Implementierung, da die Klassen und Programme, die auf deinen geschrieben Klassen basieren von deiner internen und nicht öffentlichen Bezeichnung abhängig sind. Dass PHP die komplette Datentypen-Verwaltung übernimmt ist zwar für viele ganz praktisch und spart in solchen Fällen auch Tipparbeit, ich kann mich mit dem Konzept aber nicht recht anfreunden, was aber wohl daran liegt, dass ich C/C++ bevorzuge.
In Java wirst du aber wohl um die Tipparbeit nicht herum kommen, da du dich dabei selbst um die Datentypen kümmern musst. Ich will es nicht vollkommen ausschließen, dass es nicht doch irgendwie möglich ist, da ich mich auch nicht großartig mit Java auseinander setze, allerdings gehe ich nicht davon aus, dass dein Vorhaben wie in PHP umsetzbar ist.
 
Zuletzt bearbeitet:
Das automatische Casten von Rückgabewerten wirst du in Java nicht hinbekommen. Wenn du dir mal den Source von zB Arrays.java anschaust wird dir schnell klar, dass du für jeden Rückgabewert auch eine eigene Methode brauchen wirst. Ein weiteres schönes Beispiel ist die Klasse UIManager.java mit ihren verschiedenen Gettern.

Mein Tip:
Den value Typ in der set Methode auf Object stellen, dann nicht abstract in der Mama Klasse folgende Methoden definieren:

Object get(String key) throws NoSuchElementException
boolean getAsBoolean(String key) throws NoSuchElementException, ClassCastException
Object getAsEhemann(String key) throws NoSuchElementException, ClassCastException
etc...

Damit bekommst du dein Problem wohl am Saubersten in den Griff.
 
Zuletzt bearbeitet:
Ohne jetzt alles wirklich so genau verstanden zu haben: können dir für deine Factorys eventuell Generics helfen?
 
Seh da nicht das Problem.
Einfach
if(object instanceof Class){ ((Class)object).setProperty(blub)}
Fallst mehr als ein Methode callen willst halt in ein Class object storen sonst castest da wie wild rum.

Andere Möglichkeit wäre es eine Art Container Klasse zu verwenden.
Die Container Klasse enthält alle möglichen Werte, wobei die jede Klasse die nur für sich relevanten Daten abruft.

z.b.:
class Container{String property1;String property2;int property3}

und setProperty(Container container){this.property=container.property1;}

So ein System verwend ich derzeit für ein Uni Java ME arcarde spiel da laufen alle object durch ne mehrstufe Pipe und jedes Object verwaltet sich quasi selbst. (Was auch so sein sollte)
 
Zuletzt bearbeitet:
Danke für den vielen Input, habe es bereits umgesetzt und es funktioniert perfekt. :)
 
Zurück
Oben