Discussion:
Was ist an dieser Klasse falsch?
(zu alt für eine Antwort)
Peter Heitzer
2020-07-30 07:58:08 UTC
Permalink
import java.util.*;
public class P extends Properties {
public String getProperty(String p) {
return super.getProperty(p,"de");
}
public static void main(String[] args) {
P x=new P();
x.setProperty("a","b");
System.out.println(x.getProperty(args[0]));
}
}
Es wird ohne Fehler übersetzt. Wenn man es aber startet bricht es mit
Stackoverflow ab. Ich kann mir nicht erklären, was hier passiert.
Die abgeleitete Klasse P überschreibt die Methode getProperty(String) und
ruft darin die Originalmethode getProperty(String,String) auf.
Das Laufzeitverhalten mit Stackoverflow schaut aber für mich so aus, als
ob die überschriebene Methode sich selbst aufruft.
Wer kann mir das Verhalten erklären?
--
Dipl.-Inform(FH) Peter Heitzer, ***@rz.uni-regensburg.de
Michael Paap
2020-07-30 08:40:39 UTC
Permalink
import java.util.*;
public class P extends Properties {
public String getProperty(String p) {
return super.getProperty(p,"de");
}
public static void main(String[] args) {
P x=new P();
x.setProperty("a","b");
System.out.println(x.getProperty(args[0]));
}
}
Es wird ohne Fehler übersetzt. Wenn man es aber startet bricht es mit
Stackoverflow ab. Ich kann mir nicht erklären, was hier passiert.
Die abgeleitete Klasse P überschreibt die Methode getProperty(String) und
ruft darin die Originalmethode getProperty(String,String) auf.
Das Laufzeitverhalten mit Stackoverflow schaut aber für mich so aus, als
ob die überschriebene Methode sich selbst aufruft.
Wer kann mir das Verhalten erklären?
Vorab: Es wäre sinnvoll, wenn du dein Posting nicht schon als Zitat
beginnen würdest. Wenn man dann z.B. den Code rauskopieren will, muss
man erst noch Zitatzeichen entfernen...

Zur Frage: Du rufst in deiner Methode getProperty() eine Methode der
Superklasse auf. Das könntest du übrigens auch ohne "super", weil es ja
nicht die Methode ist, die du überschrieben hast (unterschiedliche
Parameterzahl). Aber das ist nicht das Problem.

Das Problem besteht darin, dass die Methode, die du da aufrufst,
ihrerseits wieder die Methode getProperty() aufruft, die einen Parameter
mit Deklarationstyp String hat. Und das ist aufgrund dynamischer Bindung
dann wieder "deine" Methode getProperty(), womit du eine nette kleine
Endlosschleife gebaut hast.

Gruß
Michael
Peter Heitzer
2020-07-30 09:10:19 UTC
Permalink
Post by Michael Paap
import java.util.*;
public class P extends Properties {
public String getProperty(String p) {
return super.getProperty(p,"de");
}
public static void main(String[] args) {
P x=new P();
x.setProperty("a","b");
System.out.println(x.getProperty(args[0]));
}
}
Es wird ohne Fehler übersetzt. Wenn man es aber startet bricht es mit
Stackoverflow ab. Ich kann mir nicht erklären, was hier passiert.
Die abgeleitete Klasse P überschreibt die Methode getProperty(String) und
ruft darin die Originalmethode getProperty(String,String) auf.
Das Laufzeitverhalten mit Stackoverflow schaut aber für mich so aus, als
ob die überschriebene Methode sich selbst aufruft.
Wer kann mir das Verhalten erklären?
Vorab: Es wäre sinnvoll, wenn du dein Posting nicht schon als Zitat
beginnen würdest. Wenn man dann z.B. den Code rauskopieren will, muss
man erst noch Zitatzeichen entfernen...
Ich hatte es ursprünglich in die falsche Gruppe gepostet und der Einfachheit (meiner
Faulheit geschuldet) hierhin als Following gepostet. Sorry dafür.
Post by Michael Paap
Zur Frage: Du rufst in deiner Methode getProperty() eine Methode der
Superklasse auf. Das könntest du übrigens auch ohne "super", weil es ja
nicht die Methode ist, die du überschrieben hast (unterschiedliche
Parameterzahl). Aber das ist nicht das Problem.
Das Problem besteht darin, dass die Methode, die du da aufrufst,
ihrerseits wieder die Methode getProperty() aufruft, die einen Parameter
mit Deklarationstyp String hat. Und das ist aufgrund dynamischer Bindung
dann wieder "deine" Methode getProperty(), womit du eine nette kleine
Endlosschleife gebaut hast.
Zu der Erkenntnis hat mit ein Kollege mittlerweile auch gebracht. Ich habe nicht
überrissen, daß in der Superklasse die originale einparametrige nicht mehr sichtbar
ist, sondern nur die überschriebene.

Der Grund für die Ableitung der Properties Klasse ist in einem Programm von mir
gegründet. Es ist ein kleiner Webservice, der sowohl als Produktivversion als auch
als Testversion läuft. Welche Version es ist, wird beim Start durch eine Systemvariable
festgelegt, welche als Präfix dient.
Da der Service seine Parameter aus einer Datei liesst, einhält diese jeweils
einen Eintrag für Produktion und Test, z.B. Serverport=xxx bzw. TestServerport=yyy
Im eigentlichen Programm brauche ich dann keine Fallunterscheidung, da meine abgeleitete
Properties Klasse jeweils das passende Präfix vor den Namen der Property setzt.

Danke auf jeden Fall für die prompte Hilfe.
--
Dipl.-Inform(FH) Peter Heitzer, ***@rz.uni-regensburg.de
Michael Paap
2020-07-30 11:05:36 UTC
Permalink
Post by Peter Heitzer
Zu der Erkenntnis hat mit ein Kollege mittlerweile auch gebracht. Ich habe nicht
überrissen, daß in der Superklasse die originale einparametrige nicht mehr sichtbar
ist, sondern nur die überschriebene.
Das Problem ist nicht Sichtbarkeit, sondern, dass "this", das Objekt,
auf dem du hantierst, ja ein P ist. Und dann wird eben auch die Methode
von P gewählt.
Post by Peter Heitzer
Der Grund für die Ableitung der Properties Klasse ist in einem Programm von mir
gegründet. Es ist ein kleiner Webservice, der sowohl als Produktivversion als auch
als Testversion läuft. Welche Version es ist, wird beim Start durch eine Systemvariable
festgelegt, welche als Präfix dient.
Da der Service seine Parameter aus einer Datei liesst, einhält diese jeweils
einen Eintrag für Produktion und Test, z.B. Serverport=xxx bzw. TestServerport=yyy
Im eigentlichen Programm brauche ich dann keine Fallunterscheidung, da meine abgeleitete
Properties Klasse jeweils das passende Präfix vor den Namen der Property setzt.
Dann wäre mein Tipp, eben keine Subklasse zu bilden und irgendwas zu
überschreiben, sondern in P ein Properties zu /verwenden/.

Gruß
Michael Paap
Patrick Roemer
2020-07-30 12:22:23 UTC
Permalink
Post by Peter Heitzer
Der Grund für die Ableitung der Properties Klasse ist in einem Programm von mir
gegründet. Es ist ein kleiner Webservice, der sowohl als Produktivversion als auch
als Testversion läuft. Welche Version es ist, wird beim Start durch eine Systemvariable
festgelegt, welche als Präfix dient.
Da der Service seine Parameter aus einer Datei liesst, einhält diese jeweils
einen Eintrag für Produktion und Test, z.B. Serverport=xxx bzw. TestServerport=yyy
Im eigentlichen Programm brauche ich dann keine Fallunterscheidung, da meine abgeleitete
Properties Klasse jeweils das passende Präfix vor den Namen der Property setzt.
Warum nicht einfach zwei verschiedene Dateien, von denen je nach Wert
der Umgebungsvariablen die passende geladen wird?

Alternativ eine Bibliothek verwenden, die unterschiedliche
Konfigurationsblöcke bzw. -hierarchien innerhalb einer Datei explizit
unterstützt, z.B.

https://github.com/lightbend/config

Falls man doch lieber selber basteln will: Das Design der
Properties-Klasse ist eh schon fritte, alleine dadurch, dass sie von
Hashtable ableitet. Wenn man nur #getProperty() überschreibt, macht man
sich recht sicher irgendwo den Contract noch weiter kaputt - zusätzlich
zu klassischen Problemen beim Ableiten von konkreten Klassen wie im OP.
Besser also eine Wrapperklasse mit einer minimalen API, die auf die
konkreten Anforderungen zugeschnitten ist, wie von Michael vorgeschlagen.

Grundsätzlich sowieso: Favor composition over inheritance. [1]

Viele Grüße
Patrick

[1] https://en.wikipedia.org/wiki/Composition_over_inheritance
Peter Heitzer
2020-07-30 13:24:41 UTC
Permalink
Post by Patrick Roemer
Post by Peter Heitzer
Der Grund für die Ableitung der Properties Klasse ist in einem Programm von mir
gegründet. Es ist ein kleiner Webservice, der sowohl als Produktivversion als auch
als Testversion läuft. Welche Version es ist, wird beim Start durch eine Systemvariable
festgelegt, welche als Präfix dient.
Da der Service seine Parameter aus einer Datei liesst, einhält diese jeweils
einen Eintrag für Produktion und Test, z.B. Serverport=xxx bzw. TestServerport=yyy
Im eigentlichen Programm brauche ich dann keine Fallunterscheidung, da meine abgeleitete
Properties Klasse jeweils das passende Präfix vor den Namen der Property setzt.
Warum nicht einfach zwei verschiedene Dateien, von denen je nach Wert
der Umgebungsvariablen die passende geladen wird?
Weil nicht alle Properties unterschiedliche Namen haben. Es gibt auch Properties, die
in beiden Fällen gleich sind. In einer Datei ist es IMO übersichtlicher.
Wenn z.B. steht
ServerPort=12345
TestServerPort=56789

sehe ich das eher als in zwei Dateien.

Ich habe es jetzt so gelöst:
Ich leite Properties ab, aber ich definiere get(String) und get(String,String),
welche getProperties aus der Basisklasse verwenden.
--
Dipl.-Inform(FH) Peter Heitzer, ***@rz.uni-regensburg.de
Lesen Sie weiter auf narkive:
Loading...