Vererbung: Private Attribute der Oberklasse

  • Hallo,
    ich habe eine Frage bezüglich der Vererbung in Java. In Java wird ja, wenn ich den Konstruktor einer Unterklasse aufrufe, automatisch ebenfalls der Konstruktor der Oberklasse aufgerufen. Initialisiert dieser Kosntruktor der Oberklasse auch private Attribute? Wenn ja, wäre das ja unnötig, da die Unterklasse sowieso keinen Zugriff auf die Oberklasse hat.


    Um meine Frage zu verdeutlichen, hab ich ein Beispiel gemacht:

    Wird bei folgendem Befehl in der main-Klasse

    Code
    1. Unterklasse obj = new Unterklasse ();

    nun sowohl number1, als auch number2 initalisiert?
    Wird für beide Variablen Speicher gebraucht?


    Wäre es besser, Unterklasse NICHT von Oberklasse erben zu lassen, wenn nur ein logischer Zusammenhang besteht (z.B. "Card" erbt von "Deck"), Unterklasse aber nie auf Attribute oder Methoden von Oberklasse zugreifen muss?

  • Hallo,
    ich habe eine Frage bezüglich der Vererbung in Java. In Java wird ja, wenn ich den Konstruktor einer Unterklasse aufrufe, automatisch ebenfalls der Konstruktor der Oberklasse aufgerufen. Initialisiert dieser Kosntruktor der Oberklasse auch private Attribute? Wenn ja, wäre das ja unnötig, da die Unterklasse sowieso keinen Zugriff auf die Oberklasse hat.

    methoden der unterklasse haben zwar keinen zugriff auf private felder der oberklasse, aber die klasse muss trotzdem die gesamte funktionalität anbieten können, dh die von der oberklasse geerbten methoden benötigen diese felder.

    Quote

    Wird bei folgendem Befehl in der main-Klasse

    Code
    1. Unterklasse obj = new Unterklasse ();

    nun sowohl number1, als auch number2 initalisiert?

    ja

    Quote

    Wird für beide Variablen Speicher gebraucht?

    ja :)

    Quote

    Wäre es besser, Unterklasse NICHT von Oberklasse erben zu lassen, wenn nur ein logischer Zusammenhang besteht (z.B. "Card" erbt von "Deck"), Unterklasse aber nie auf Attribute oder Methoden von Oberklasse zugreifen muss?

    für card und deck wäre komposition wohl eine angemessenere beziehung als vererbung. in java hast du dann zb in Card ein feld vom typ Deck und in Deck ein feld vom typ List<Card>.


    lg

  • Wenn ja, wäre das ja unnötig, da die Unterklasse sowieso keinen Zugriff auf die Oberklasse hat.

    Nein, das ist nicht unnötig. Methoden in der Oberklasse können Zugriffe auf private Variablen durchführen. Diese Methoden können von der Unterklasse oder von anderen Klassen aufgerufen werden, sie müssen ja nicht private sein.


    Wird bei folgendem Befehl in der main-Klasse

    Code
    1. Unterklasse obj = new Unterklasse ();

    nun sowohl number1, als auch number2 initalisiert?

    Ja.

    Wird für beide Variablen Speicher gebraucht?

    Ja.

    Wäre es besser, Unterklasse NICHT von Oberklasse erben zu lassen, wenn nur ein logischer Zusammenhang besteht (z.B. "Card" erbt von "Deck"), Unterklasse aber nie auf Attribute oder Methoden von Oberklasse zugreifen muss?

    Trenne Interface und Implementierung.


    Sei A deine bisherige Oberklasse und B deine Unterklasse. Wir führen nun zwei Interfaces IA und IB ein, welche die nach außen hin sichtbaren Methoden, die von A und B implementiert werden sollen, enthalten.


    Besteht nun ein logischer Zusammenhang von IA und IB, d.h. im Sinne des Ersetzbarkeitsprinzips soll überall dort, wo eine Instanz von IA erwartet wird, auch eine Instanz von IB verwendet werden können, dann ist es sinnvoll, IB von IA abzuleiten.


    Ob die konkrete Klasse B nun von A erbt oder nicht, ist dann ein anderes Paar Schuhe. Willst du Code von A in B wiederverwenden oder nicht? Aber ganz egal, wie du dich entscheidest: Wenn du an jeder Stelle, wo du bisher A erwartest, nun IA erwartest, wirst du dort sowohl A als auch B einsetzen können, unabhängig davon, ob B nun von A abgeleitet wird oder nicht. Wichtig ist, dass IB von IA erbt.


    In deinem Beispiel ist die Frage: Will ich überall dort, wo ich Deck erwarte, auch Card verwenden können? Ist das sinnvoll?


    Ich behaupte nein. Ich würde Deck als eine Menge oder Liste von Karten aufzubauen (Set<Card> oder List<Card>). Eine Untertypbeziehung bringt nichts.


    Wenn du Interesse an diesen Problemstellungen hast (welche im Übrigen ganz zentral für die objektorientierte Programmierung sind), dann empfehle ich als Einstieg die Lektüre des Skriptums zur Lehrveranstaltung Objektorientierte Programmierung (oder den Besuch derselben Lehrveranstaltung): http://www.complang.tuwien.ac.…iert/skript07-1seitig.pdf


    Und schließlich hab ich mit meinem Posting jetzt so lange gebraucht, dass michi204 schon viel schneller und weniger ausschweifend geantwortet hat. :)

  • uuuhm... nein?


    Code
    1. Unterklasse obj = new Unterklasse ();

    also hier wird schon auf jeden fall mal nicht number1 (bzw hast du nur "number geschrieben aber egal) was in Oberklasse ist initialisiert


    da der konstruktor von Unterklasse ja so aussieht


    Code
    1. Unterklasse () {
    2. number2 = 13;
    3. }

    alles was hier passiert ist das initialisieren von number2 mit 13


    ich meine natürlich initialisiert java per default number1 mit 0 aber der punkt ist dass der konstruktor von Oberklasse nie aufgerufen wird, deswegen wird auch number1 nicht mit 10 initialisiert


    erst hier wird auch number1 mit 10 initialisiert


    Code
    1. Unterklasse () {
    2. super();
    3. number2 = 13;
    4. }

    durch das super() sagt man explizit dass der konstruktor von Oberklasse aufgerufen werden soll wo dann die tatsächliche initialisierung von number1 mit 10 stattfindet


    zu vererbung allgemein, das mit card und deck


    vererbung ist einfach eine ist-ein beziehung, klar kann man sie auch irgendwie und irgendwo einsetzen, man kann häuser statt mit nägeln und zement mit duck tape bauen aber die frage ist wie lange das gut geht


    "ist eine card ein deck?" --> nein


    ein deck hat zb die methoden


    Code
    1. void shuffle();
    2. Card drawRandomCard();
    3. Deck getAllCards(CardType type);

    wenn ich card von deck vererbe hab ich diese methoden immer noch, aber kann ich eine einzelne karte mischen, eine zufällige karte daraus ziehen usw? nope


    vererbung ist meist dort sinnvoll wenn man eine basisklasse hat die bestimmte sachen kann und dann spezielle unterklassen, in den meisten fällen ist die basisklasse auch abstrakt, sie kann also alleine nicht existieren


    ein beispiel dafür wäre halt das paradebeispiel: Tier
    sagen wir ich will Hunde, Katzen, ZauberPonys und BlackRubberDildoUniCorns (welche einen black rubber dildo statt einem horn haben)
    ich kann jetzt meine Hunde, Katzen usw erstellen als klassen aber dann merke ich, zomfg die haben alle eine getRace(), getAge(), isPredator() und was weiss ich was nicht methode und entsprechend variablen die fast überall sich wiederholen


    also mache ich eine abstrakte basisklasse Tier wo ich alle gemeinsamekeiten die meine Tiere haben rein tu und implementiere nur noch konkret in die unterklassen ihre einzigartigen eigenschaften
    Katze hat drinkMilk(), Hund hat bark(), und BlackRubberDildoUniCorn hat rape()


    fast immer wenn man eine richtige vererbungshierarchie designed hat dann sind alle klassen bis auf die ganz unten, also die blätter in dem vererbungs-baum abstrakt (natürlich ist das aber nicht immer so, aber meistens)

    [FONT=Arial, Helvetica, sans-serif](\__/) [/FONT]
    [FONT=Arial, Helvetica, sans-serif] (='.'=) [/FONT]This is Bunny. Copy Bunny into your signature to help
    [FONT=Arial, Helvetica, sans-serif](")_(")[/FONT] him on his way to world domination.

    Edited once, last by Vevusio ().


  • Ehm wenn mich jetzt nicht alle guten Javageister verlassen haben, wuerde ich schon sagen das number mit 10 initaliziert wird. Denn new Unterklasse() ruft natuerlich den default Konstruktor der Oberklassen auf.

  • Stimmt, der default Konstruktor wird immer aufgerufen, sonst gebs ja das "Oberobjekt" nicht.


    "super" ist so wie "this" nur zeigt es auf die Oberklasse.


    Warum manchmal Leute in einem Konstruktor der Unterklasse ein super() aufrufen obwohl die Oberklasse nur einen Konstruktor hat, versteh ich bis heute nicht ... Hats einen Grund ?

  • hm stimmt kubuntu du hast recht, ich wusste nicht dass java trotzdem den default konstruktor von der darüberliegenden klasse aufruft


    ich würde sagen der grund wieso man trotzdem das super() hinschreibt ist ziemlich offensitchtlich: leserlichkeit und verständlichkeit
    nachteile bringt es ja wohl auch keine mit sich

    [FONT=Arial, Helvetica, sans-serif](\__/) [/FONT]
    [FONT=Arial, Helvetica, sans-serif] (='.'=) [/FONT]This is Bunny. Copy Bunny into your signature to help
    [FONT=Arial, Helvetica, sans-serif](")_(")[/FONT] him on his way to world domination.

  • Es ist allerdings bemerkenswert, mit welcher Selbstverständlichkeit Du deine (falsche) Aussage nach den beiden ohnehin schon völlig korrekten Antworten von michi204 und Paulchen getätigt hast (ohne Dich damit beleidigen zu wollen).

    "I don't think that Debian can really compete with Gentoo. Sure it might be okay, but when it comes to dependencies, you probably are still going to have to get them all on your own. Or is there something like portage in the Debian world as well?"

  • Vielen Dank für die vielen Antworten, hat mir sehr geholfen :)


    Ich hab nun ein bisschen weiter programmiert und stehe vor einem ähnlichen Problem. Ich möchte eine KI programmieren, d.h. ich möchte im Endeffekt gegen den Computer spielen können.
    Jetzt gibt es im Poker ja verschiedene Spielrunden (vor den Flop, nach dem Flop, am Flop, am Turn, am River). Die Spieler müssen in jeder Spielrunde anders reagieren.


    Ich habe derzeit eine Klasse Player.
    In jeder Spielrunde müssen die Spieler anders reagieren, sie müssen z.B. erkennen, welches Blatt sie vor dem Flop bzw. nach dem Flop halten => Methoden der Klasse Spieler. Jetzt wären das aber eine ganze Menge Methoden und ich suche nach einer Möglichkeit, diese zu Gruppieren.


    Ich habe schon einige Möglichkeiten durchgedacht, bin mir aber nicht sicher, welche objektorientiert gedacht, am sinnvollsten ist.


    a)
    class Player mit nur wenigen Methoden (setzten, passen, schieben)
    class Gamplay
    class Preflopplay extends Gameplay
    class Postflopplay extends Gameplay
    class Flopplay extends Postflopplay
    Hier wären die Aktionen, welche ja eigentlich der Spieler macht (Hand analysieren - also die Strategie) in einem eigenen "Gamplay-Baum". Die "Denkarbeit" ist praktisch in einer anderen Klasse als die echten Aktionen, wie setzen.
    Das wäre denk ich sehr übersichtlich. Die Frage ist aber, ob das nichtder Objektorientierung widerspricht, da "Flopplay" ja eigentlich kein Objekt ist, sondern nur Methoden beinhaltet, die mit dem Spieler in Zusammenhang stehen. Vll. wäre es angebracht, die Gameplay-Klassen als abstrakte Klassen zu schreiben.


    b)
    class Player mit allen Methoden
    Egal ob setzten, passen oder denken. Strategie und konkrete Aktionen wären hier in der gleichen Klasse. Logisch finde ich das schon, da der Spieler ja setzt, passt und denkt. Allerdings fände ich es unübersichtlich, wenn praktisch das gesamte Gameplay in einer Klasse wäre.


    c)
    class Player mit nur wenigen Methoden (setzten, passen, schieben)
    class Gamplay extends Player
    class Preflopplay extends Gameplay
    class Postflopplay extends Gameplay
    class Flopplay extends Postflopplay
    Ähnlich wie bei a), nur dass diesmal Gameplay von Spieler erbt. Kommt mir aber unlogisch vor, da Preflopplay sicher kein Player ist - daher scheidet diese Möglichkeit für mich aus.


    Wäre für jede Hilfe dankbar, werde mir auch den verlinkten Text durchlesen. Leider fange ich erst in einem Jahr mit dem Studium an. Viel kann man eh durch openbooks ect. lernen, aber bei solchen Fragen muss ich erst ein Gefühl entwickeln, in welche Richtung gedacht werden muss. T
    Thx im voraus :)