implements richtig nutzen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • implements richtig nutzen

    Guten Morgen beisammen,

    irgendwie steckt hier der Wurm drin, aber wieso?

    Quellcode

    1. public class Tier {
    2. boolean lebtInEuropa;
    3. String essen = "Fleisch";
    4. void geraeusch() {
    5. System.out.println("wau");
    6. }
    7. void hunger() {
    8. System.out.println("*um den Napf*");
    9. }
    10. static void spritzen(Tier a){
    11. a.weinen();
    12. }
    13. void weinen() {
    14. System.out.println("*heul*");
    15. }
    16. public static void main (String args[]) {
    17. Hund Bello = new Hund();
    18. Hund Bella = new Hund();
    19. Katze Muschi = new Katze();
    20. Huhn Tommy = new Huhn();
    21. Hahn Tammy = new Hahn();
    22. Muschi.hunger();
    23. Tommy.hunger();
    24. Bello.hunger();
    25. Muschi.geraeusch();
    26. Tommy.geraeusch();
    27. Bello.geraeusch();
    28. Muschi.miauen();
    29. System.out.println("---------------------");
    30. Tier[] tiere = new Tier[4];
    31. tiere[0] = Bello;
    32. tiere[1] = Muschi;
    33. tiere[2] = Tommy;
    34. tiere[3] = Tammy;
    35. Hund[] hunde = new Hund[1];
    36. hunde[0] = Bello;
    37. hunde[0] = Bella;
    38. //System.out.println(ArraystoString(hunde));
    39. for(int i = 0; i< tiere.length;i++){
    40. System.out.println(tiere[i] + ":");
    41. tiere[i].hunger();
    42. tiere[i].geraeusch();
    43. //tiere[i].miauen(); // geht nicht, da miauen nur in Katze vorkommt
    44. spritzen(tiere[i]);
    45. System.out.println("ich esse " + tiere[i].essen);
    46. System.out.println("---------------------");
    47. }
    48. System.out.println("---------------------");
    49. Bello.seiFreundlich();
    50. Bella.spielen();
    51. }
    52. public interface Haustier {
    53. public abstract void seiFreundlich();
    54. public abstract void spielen();
    55. }
    56. }
    57. class Hund extends Tier implements Haustier {
    58. public void seiFreundlich(){
    59. System.out.println("ich bin freundlich!");
    60. }
    61. public void spielen(){
    62. System.out.println("spiel mit mir!!");
    63. }
    64. }
    65. class Katze extends Tier {
    66. void miauen() {
    67. System.out.println("miau1");
    68. }
    69. void geraeusch() {
    70. System.out.println("miau");
    71. }
    72. void hunger() {
    73. System.out.println("*kratzen*");
    74. }
    75. void weinen() {
    76. System.out.println("*heul_katze*");
    77. }
    78. }
    79. class Huhn extends Tier {
    80. String essen = "Körner";
    81. void geraeusch() {
    82. System.out.println("guckguck");
    83. }
    84. void hunger() {
    85. System.out.println("*picken*");
    86. }
    87. void weinen() {
    88. System.out.println("*heul_huhn*");
    89. }
    90. }
    91. class Hahn extends Huhn {
    92. void geraeusch() {
    93. System.out.println("gackgack");
    94. }
    95. void weinen() {
    96. System.out.println("*heul_hahn*");
    97. }
    98. }
    Alles anzeigen


    Die Probleme liegen bei der Implementation des Interface "Haustier" in "Hund" und seinen Aufrufen
    -Bello.seiFreundlich(); und
    -Bella.spielen();

    Irgendwie schmeißt mir mein Lehrbuch noch viele Codeschnipsel hin, die ich selbst zusammenschustern muss. Mein Lerneffekt = 0 :(
    Wie man sieht ist mein Code wahrscheinlich auch total wirr, irgendwie basieren meine Codeeinfügungen eher auf dem Trial and Error-Prinzip.


    Könnte mir vielleicht jemand sagen, wie ich "Implements" in diesem Bsp. richtig nutze?

    Danke

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von kingele ()

  • soweit ich das sehe ist in Hund das Interface korrekt implementiert.
    Du darfst nur ds Interface nicht innerhalb der Klasse Tier definieren, sondern musst es außerhalb, auf der gleichen "Stufe" wie die Klassen, definieren. Quasi reicht es die eine geschweifte Klammer zu versetzten:

    Quellcode

    1. public class Tier {
    2. //[...]
    3. public static void main (String args[]) {
    4. //[...]
    5. }
    6. }
    7. public interface Haustier {
    8. public abstract void seiFreundlich();
    9. public abstract void spielen();
    10. }
  • mache mal

    Quellcode

    1. public static interface Haustier

    anstatt

    Quellcode

    1. public interface Haustier


    Ansonsten kannst du nur von einem Objekt Tier auf das Interface zugreifen und nicht von eine Klasse aus.

    Generell würde ich dir empfehlen innere Klassen/Interfaces als Anfänger nicht zu verwenden. Es geht alles auch mit normalen Klassen/Interfaces und die zusätzliche Datei tut nun wirklich nicht weh.
  • Hallo Kingele,

    Vorab mal, dieser Beitrag enthält ein bisschen Theorie aber ich geb mir Mühe das ganze so einfach wie möglich zu schreiben ;).

    Also erstmal, wozu braucht man das Sprachmittel des Interfaces. Es gibt ja immer einen der eine Klasse benutzen will, in deinem Beispiel wird das Tier in der main-Methode verwendet. Du gehst das ganze nur von der falschen Seite an. Ein Interface ist dazu da, wenn man weiß, dass es mehrer "Untertypen" gibt, die nach Außen die selben Funktionen zur Verfügung stellen aber sich unterschiedlich beim Aufruf verhalten. Klingt wahrscheinlich komplizierter als es ist. Dein erster Denkfehler: Das Tier ist nicht die kongrete Implementierung (class) sonder die abstrakte Definition (interface) und definiert damit, welche Methoden ein Tier hat.

    Quellcode

    1. package test;
    2. public interface Tier
    3. {
    4. public void geraeusch();
    5. public void hunger();
    6. public void weinen();
    7. }


    Damit haben wir jetzt definiert jedes Tier macht Geräusche, zeigt irgendwie das es Hunger hat und kann weinen.

    Als nächstes willst du nun sagen, dass es Haustiere gibt. Im Grunde ist ein Haustier ein Tier + kann noch spielen und zeigt das es freundlich ist. Das heißt wir erweitern das Interface Tier um diese beiden Methoden:

    Quellcode

    1. package test;
    2. public interface HausTier extends Tier
    3. {
    4. public void seiFreundlich();
    5. public void spielen();
    6. }


    So als nächstes machen wir uns an die kongrete Implementierung der Haustiere, sprich wir definieren die Methoden die das Interface HausTier vorgibt für Hund und Katze.

    Quellcode

    1. package test;
    2. public class Hund
    3. implements HausTier
    4. {
    5. //Methoden von Tier
    6. public void geraeusch()
    7. {
    8. System.out.println("wau");
    9. }
    10. public void hunger()
    11. {
    12. System.out.println("*um den Napf*");
    13. }
    14. public void weinen()
    15. {
    16. System.out.println("*heul*");
    17. }
    18. //Zusätzliche Methoden von Haustier
    19. public void seiFreundlich()
    20. {
    21. System.out.println("ich bin freundlich!");
    22. }
    23. public void spielen()
    24. {
    25. System.out.println("spiel mit mir!!");
    26. }
    27. }
    Alles anzeigen


    Quellcode

    1. package test;
    2. public class Katze implements HausTier
    3. {
    4. //Methoden von Tier
    5. public void geraeusch()
    6. {
    7. System.out.println("miau");
    8. }
    9. public void hunger()
    10. {
    11. System.out.println("*kratzen*");
    12. }
    13. public void weinen()
    14. {
    15. System.out.println("*heul_katze*");
    16. }
    17. //Zusatzmethoden von Haustier
    18. public void seiFreundlich()
    19. {
    20. System.out.println("Schnurren");
    21. }
    22. public void spielen()
    23. {
    24. System.out.println("Mäuse jagen");
    25. }
    26. }
    Alles anzeigen


    Also wie du siehst definieren die Interfaces Tier und Haustier die Methoden und Katze und Hund implementieren diese unterschiedlich.Somit hoffe ich, dass dir klar geworden ist wozu Interfaces da sind.

    Aber um das Thema abzurunden führ ich noch schnell die abstrakten Klassen ein. Dazu greif ich wieder dein Beispiel mit dem Huhn auf. Ein Huhn ist ein Tier, sprich es implementiert die Methoden hunger und weinen. Das weibliche Huhn, die Henne, macht aber andere Geräusche wie das männliche, der Hahn. Das hast du ja auch schon erkannt.

    Daher kannst du eine Klasse Huhn definieren, das die Methoden hunger und weinen implementiert. Die Methode geraeusch wird aber offen gelassen. Damit das geht, muss die Klasse als abstrakt gekennzeichnet werden. Abstrakt heißt, dass diese Klasse noch nicht vollständig ist, und somit keine Objekte von der Klasse angelegt werden können.

    Quellcode

    1. package test;
    2. public abstract class Huhn implements Tier
    3. {
    4. //Implementierte Methoden da dies bei Henne und Hahn gleich bleibt
    5. public void hunger()
    6. {
    7. System.out.println("*picken*");
    8. }
    9. public void weinen()
    10. {
    11. System.out.println("*heul_huhn*");
    12. }
    13. //Offen gelassene Methode, muss nicht hingeschrieben werden
    14. public abstract void geraeusch();
    15. }
    Alles anzeigen


    Als letzten Schritt definieren wir noch Henne und Hahn. In denen legen wir fest, was welches Geräusch die Henne bzw. der Hahn macht:

    Quellcode

    1. package test;
    2. public class Henne extends Huhn
    3. {
    4. public void geraeusch()
    5. {
    6. System.out.println("guckguck");
    7. }
    8. }


    Quellcode

    1. package test;
    2. public class Hahn extends Huhn
    3. {
    4. public void geraeusch()
    5. {
    6. System.out.println("gackgack");
    7. }
    8. }


    Als letztes folgt noch der Test des ganzen:

    Quellcode

    1. package test;
    2. public class Test
    3. {
    4. public static void main(String[] args)
    5. {
    6. Tier[] tiere = new Tier[4];
    7. tiere[0] = new Hund();
    8. tiere[1] = new Henne();
    9. tiere[2] = new Katze();
    10. tiere[3] = new Hahn();
    11. for (Tier tier : tiere)
    12. {
    13. //Methoden von Tier testen
    14. tier.geraeusch();
    15. tier.hunger();
    16. tier.weinen();
    17. //Wenn das Tier ein Haustier ist
    18. if(tier instanceof HausTier)
    19. {
    20. ((HausTier) tier).seiFreundlich();
    21. ((HausTier) tier).spielen();
    22. }
    23. }
    24. }
    25. }
    Alles anzeigen


    Ich hoffe dir ist einigermaßen klar geworden, wofür interfaces und abstrakte Klassen da sind.

    Noch abschließend zwei Bemerkungen. 1. Das mit instanceof ist nicht umbedingt schön und sollte nicht exersiv genutzt werden. 2. Wenn du mein Beispiel zum Laufen bekommen willst, muss das ganze im Paket test liegen. Das Paket ist notwendig, weil sonst der Compiler die Abhängigkeiten zwischen den einzelnen Klassen nicht auflösen kann.

    Falls du dich wunderst wieso ich das essen und lebtInEuropa weggelassen habe. Zum einem weil das mit dem Konzept von Interfaces nichts zu tun hat, und weil so wie du es lösen wolltest, Designtechnisch mehr als hässlich ist.

    Zusammenfassend:

    Interfaces sind dazu da, wenn man weiß dass mehrere Klassen die selben Methoden anbieten sollen, diese aber ein unterschiedliches Verhalten haben sollen.

    Wenn Klassen teilweise das selbe Verhalten haben aber einzelne Methoden unterschiedlich haben kann man das selbe Verhalten in einer abstrakten Klasse beschreiben.

    HTH

    ButAlive
  • Hallo,

    vielen Dank für deine detaillierte Ausführung. Entschuldige bitte, dass ich erst jetzt antworte, aber ich wollte mir dafür eine ruhige Minute nehmen.

    ich muss ja jetzt ehrlich gestehen, dass ich ein wenig verwirrt bin. Mein Buch (Java - Head First, O'reilly) sagt mir eigentlich genau das Gegenteil.
    "Implements werden immer dann benutzt, wenn man in einem Abhängigkeitsbaum verschiedene Tiere als abstracte Klassen verzweigt hat; also z.B hundeartig und katzenartig (das beschreibt deren Gangart, Essverhalten etc), darunter zählen u.a. Hund und Katze, aber auch z.B. Löwe. Daher können wir hunde- und katzenartig nicht mit haustierartig 'extenden'."
    Hoffe, ich konnte das irgendwie verständlich rüberbringen.

    Danke für das Wiederholen der abstracten Klassen, ich wär z.B nicht darauf gekommen, noch mal eine Klasse Huhn zu machen ;)


    Falls du dich wunderst wieso ich das essen und lebtInEuropa weggelassen habe. Zum einem weil das mit dem Konzept von Interfaces nichts zu tun hat, und weil so wie du es lösen wolltest, Designtechnisch mehr als hässlich ist.

    Was meinst du damit? Weil ich sie nicht benutzt habe? Okay, ist vielleicht nicht ganz sauber sowas im Konstruktor zu deklarieren, aber da das eh nur ein Testfile ist, wollte ich nicht unbedingt auf sauberes Arbeiten achten ;)


    Noch eine allgemeine Frage:
    Hau ich die versch. Klassen in eigene Datein, oder ist das i.O. das alles in einem File ist?!


    Vielen Dank!
  • Ich glaube die ganzen erzwungenen Beispiele mit Hunden, Katzen etc. verwirren blos.
    Es ist im Grunde ganz einfach:
    Abstrakte Klassen haben den Vorteil, dass sie schon einige Methoden implementieren können. Die Unterklasse muss also nur das wirklich Notwendige implementieren.
    Interfaces haben den Vorteil, dass man davon beliebig viele in einer Klasse implementieren könnte, während man nur von einer (abstrakten) Klasse erben kann. Allerdings kann man in einem Interface selbst nichts implementieren.
  • Hallo,

    Wieso du verwirrt bist kann ich dir relativ kurz erklären: Du gehst von einer anderen Welt aus als ich.

    So jetzt mal wieder etwas theoretisch. Dein Beispiel assoziert etwas in mir, denn ich kenn deine Problemstellung nicht. Ich seh dein Beispiel mit Hund, Katze und Huhn und denk mir ja klar, der Kerl will nen Bauernhof bauen. Das ganze nennt man theoretisch gesprochen Domäne. Eine Domäne ist nichts anderes als ein Ausschnitt der Welt, du willst aber anscheinend die ganze Welt abdecken. Meine Domäne in der ich denke ist der Bauernhof, im Bauernhof ist es relativ unwahrscheinlich, dass mal so ein Löwe rumrennt. Um es mir jetzt einfacher zu machen, sag ich mal du willst nicht die Welt modellieren (etwas anderes als etwas in ein Modell bringen, machen wir Softwareentwickler ja nicht), sondern einen Zoo. Gut in einem Zoo laufen auch andere Katzen als Hauskatzen rum, da geb ich dir und deinem Buch (BTW eins das ich für sehr gut halte) recht.

    Die Frage ist nun wie sieht denn der Zoo aus.

    Im Zoo hast du wie gehabt dein Tier, im Zoo kann es auch Haustiere geben, wenn du an den Streichelzoo denkst und vielleicht läuft da ja auch eine Katze rum. Hund und Huhn lass ich der Einfachheit halber mal weg, und bau die Katze ein bisschen um. Ich bau jetzt einfach mal das Interface Tier auch etwas um, find ich sinniger. Das ganze kannst du auch im Wiki-Eintrag von mir nachlesen. Auf das getLieblingsEssen() geh ich später nochmal detalierter ein, weil das was mit deiner 2. Frage zu tun hat.

    Quellcode

    1. public interface Tier
    2. {
    3. public void geraeusch();
    4. public String getLieblingsEssen();
    5. public void bewegen();
    6. }


    Als nächstes überlegen wir uns was haben denn alle Katzen gemeinsam. Ich würde sagen, alle Katzen bewegen sich eher springend. Eine Hauskatze hat aber ein anderes Lieblingsessen als ein Löwe und das klägliche Miau kannst du auch nicht mit einem Brüllen gleichsetzen. Also bauen wir uns eine abstrakte Klasse Katze in der wir die Methode bewegen implementieren.

    Quellcode

    1. public abstract class Katze implements Tier
    2. {
    3. public void bewegen()
    4. {
    5. System.out.println("spring");
    6. }
    7. }


    Nachdem wir festgelegt haben, wie sich Katzen bewegen können wir nun als erstes den Löwen bauen.

    Quellcode

    1. package test;
    2. public class Loewe extends Katze
    3. {
    4. public void geraeusch()
    5. {
    6. System.out.println("brüll");
    7. }
    8. public String getLieblingsEssen()
    9. {
    10. return "Gazelle";
    11. }
    12. }
    Alles anzeigen


    So jetzt machen wir uns an die Hauskatze. Die Hauskatze ist eine Katze und ein HausTier. Haustier bleibt von oben gleich.

    Quellcode

    1. package test;
    2. public class HausKatze extends Katze implements HausTier
    3. {
    4. public void seiFreundlich()
    5. {
    6. System.out.println("Schnurren");
    7. }
    8. public void spielen()
    9. {
    10. System.out.println("Kratzbaum kratzen");
    11. }
    12. public void geraeusch()
    13. {
    14. System.out.println("Miau");
    15. }
    16. public String getLieblingsEssen()
    17. {
    18. return "Mäuse";
    19. }
    20. }
    Alles anzeigen


    So jetzt haben wir deinen Zoo, zumindest für den Ausschnitt der uns interessiert, fertig gebaut.

    Die Frage ist nun, wenn ich in meiner Domäne Bauernhof bin, wieso sollte ich meinen Code so weit aufblasen und eine Abstraktions-Ebene (abstrakte Katze) einführen, wenn ich nie auf meinem Bauernhof eine andere Katze als eine Hauskatze hab? Ich hoffe mal, dass du das soweit nachvollziehen kannst. Merk dir an der Stelle, du modellierst immer nur einen Ausschnitt der Welt, vermeide zusätzliche Komplexitäten, denn die musst du später irgendwann mal wieder pflegen. Modellier also nur das was du wirklich brauchst.

    Aber ich hab dir ja versprochen auf deine öffentlichen Felder (essen und lebtInEuropa) einzugehen.

    Da stößt du auf das Thema Kappselung und "Information hiding". Was das genau bedeutet? Solche Felder, so nennt man Objekt-Variablen, also Variablen auf die man über ein Objekt zugreifen kann, sollten immer private sein. Wahrscheinlich verwirr ich dich jetzt noch ein bisschen mehr ;), aber dafür bin ich ja da.

    Also von den zugriffs-Modifikatoren private, public, protected und "package friendly" hast du sicher schon gehört. Wenn ein Feld nun private ist, kann es nur von dem Objekt aus drauf zugreifen eine andere Klasse darf es nicht. Sicher ist das so wie du es gemacht hast ein einfacher Weg, aaaaabbbbeeeer jetzt kann jeder deinen Löwen nach Europa setzten, weil ja jeder das Feld lebtInEuropa ändern kann. Was du willst ist, dass andere Klassen nur einen lesenden Zugriff auf das Feld haben. Dazu nützt man die so genannten getter - oder bei boolean Werten is. <klugscheiß>Nennt sich im Fachchinesisch Property</klugscheiß>.

    Und noch eins zu dem Thema, dann hör ich auch schon wieder auf, hab dir wahrscheinlich eh schon wieder viel zu viel Informationen gegeben. Felder haben in Interfaces überhaupt garnichts zu suchen. Das sagt dir schon der 2. Name von Feld, Objekt-Variable. Von Interfaces kannst du keine Objekte erstellen, damit hat sich da jede Diskussion ergeben. Nicht alles was mit einer Sprache machbar ist, sollte man machen.

    Und noch zu deiner letzten Frage. Ja jede Klasse/interface kommt in eine eigene Datei. Nimm dir eine IDE, auch wenn es jetzt hier Leute gibt die gleich aufschreien, nein lern es erst mal per Hand und Editor. Eclipse (eclipse.org) oder Netbeans (netbeans.org) gibts kostenlos im Netz.

    so far and thanks for all the fish

    ButAlive

    P.S.: Ich versuch gerade meine Erfahrung vom Software-Design und meiner Erfahrung als Tutor unter einen Hut zu bringen. Wenn ich dir zu theoretisch bin, sag es ruhig. Ich bin für jede Kritik mehr als dankbar.
  • Perfekt, genau so hab ich mir das vorgestellt!
    Ich bin auch wirklich von dem Modell "Zoo" ausgegangen.

    Mir haben auch deine theoretischen Ausflüge sehr gefallen, weil sich das perfekt zum Gelesenen ergänzt hat, macht immer wieder Spaß von einem erfahrenen Programmierer Tipps zu kriegen!
    Hast du das o.g. Buch auch? Kannst du mir dann sagen, warum das mit dem implements anders herum dargestellt wird, ist das einfach nur ein anderer Programmierstil? Funktioniert ja jedenfalls auch!

    Deinen Wiki-Artikel werde ich mir gleich durchlesen!

    Weiter so ;)

    Vielen Dank!
  • Hallo,
    also so ganz kann ich die Aussage aus deinem Buch nicht nachvollziehen, und leider hab ich es zur Zeit nicht zur Hand. Ich weiß nicht, ob das Zitat ein wörtliches Zitat ist oder von dir so interpretiert. Daher, bevor ich anfang großartig zu spekulieren, können wir uns ja mal den Vererbungsbaum anschauen. Ich hab ihn dir mal angehängt.

    In etwa stimmt ja die Aussage, bis darauf, dass wir hier in unserem Beispiel kein Hundeartig haben sondern Hund direkt von Haustier ableiten. Ich denk mal, das sich die Aussage auf ein kongretes Beispiel im Buch bezieht. Eine generelle Bedeutung würde ich dem aber nicht beimessen. Eigentlich heißt die Aussage, keine kongrete Klasse darf ein Interface implementieren sondern nur abstrakte Klassen. Und kongrete Klassen müssen dann von diese abstrakten Klassen erben. Aber das würde nicht gehen. Damit könntest du nie die Hauskatze bauen, denn das würde ja bedeuten, ich bräuchte noch eine abstrakte Klasse "Haustierartig" die das Interface Haustier implementiert und Hauskatze erbt dann von Haustierartig und Katzenartig. Da es aber in Java keine Mehrfachvererbung gibt, geht das nicht.

    Aber wie gesagt, ich kann nur spekulieren. Ich denk, dass es eher ein Verständnisfehler von deiner Seite ist. Vielleicht findest du ihn ja ;).

    mfg
    ButAlive

  • Eigentlich heißt die Aussage, keine konkrete Klasse darf ein Interface implementieren sondern nur abstrakte Klassen. Und konkrete Klassen müssen dann von diese abstrakten Klassen erben.

    Kann sein das das ein spezielles Programmierkonzept ist. Generell formuliert ist es jedoch falsch.
    Eine konkrete Klasse kann zig Interfaces implementieren ohne abstrakt zu sein.
    Eine abstrakte Klasse kann auch zig Interfaces implementieren, muss aber nicht zwangsläufig die Methoden implementieren. Die Klasse ist ja abstrakt. Die davon erbende konkrete Klasse muss das dann aber nachholen.
  • Hallo beisammen,

    ich will natürlich nicht abstreiten, dass es mein Fehler war, aber ich werde gleich nochmal ins Buch gucken, um das Gegenteil zu beweisen ;)
    Hier schon mal der Vererbungsbaum aus dem Beispiel, ich meine Umsetzung habe ich wie gesagt das hunde-/ und katzenartig weggelassen.

    Die beiden Haustiere "Hund" und "Katze" werden durch das Interface "Haustier" erweitert.
    (das Bild hab ich aus dem Buch nachgebastelt :))
    Klick


    Ciao

    //Edit:
    ich finds nicht mehr :(
    ^^

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von kingele ()

  • Verebung ist nicht immer die Lösung der Wahl

    Bei der Abbildung der Realität über Vererbung hat man in Java das Problem,
    dass Vererbung nur eine Richtung kennt, man nennt das auch dominante
    Dekomposition.

    Stell Dir vor, eine Firma würde Ihre Unterlagen nach Angeboten, Aufträgen,
    Lieferscheinen und Rechnungen in verschiedene Ordner einordnen.

    Wenn alle Unterlagen zu einem Kunden benötigt werden, muss man in
    verschiedenen Ordnern nachsehen.

    In Java gibt es nun mal keine Mehrfach-Vererbung.

    Das kann man aber über das Strategy-Pattern lösen
    (Info dazu gibts in Wikipedia).

    Ich habe mal ein Beispiel dazu gemacht
    groups.google.de/group/de.comp…n+Heiner#605a1e2422cd310b

    Und jede Klasse in eine eigene Datei packen
    (Die Dateien beginnen immer mit der Zeile package ....).