1. Dashboard
  2. Forum
    1. Unerledigte Themen
  3. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team-Mitglieder
    4. Trophäen
    5. Mitgliedersuche
  4. Tutorial Bereich
  • Deutsch
  • Anmelden
  • Registrieren
  • Suche
Dieses Thema
  1. Informatik Forum
  2. Webmaster & Internet
  3. Entwicklung

Vector Generizität

  • Steff100
  • 5. Januar 2009 um 14:50
  • Unerledigt
  • Steff100
    6
    Steff100
    Mitglied
    Punkte
    330
    Beiträge
    50
    • 5. Januar 2009 um 14:50
    • #1

    Ich habe eine abstrakte Klasse, wo es einen Vector mit der eigenen Klasse gibt:

    Code
    public class MyClass {
    
    
         public Vector<MyClass> myVector = new Vector<MyClass>();
    
    
         public Node(...) {
              ....
         }
    
    
         ....
    
    
    }
    Alles anzeigen

    Da die Klasse abstrakt ist, wird diese natürlich vererbt und somit verändert sich auch der Typ im Vektor zu der Klasse, die hierbei die Klasse erbt, dh:

    MyNewClass1 erbt von MyClass
    --> brauche --->
    Vector<MyClass> zu Vector<MyNewClass1>

    Hierbei habe ich versucht mit Wildcards zu arbeiten:

    Code
    Vector<? extends MyClass>

    jedoch kann ich mit diesen Wildcards nicht instanzieren. Wie kann ich hierbei mein Problem lösen??

  • a9bejo
    21
    a9bejo
    Mitglied
    Reaktionen
    42
    Punkte
    4.697
    Beiträge
    913
    • 6. Januar 2009 um 04:06
    • #2

    Ich glaube dein Problem ist, das Du Vererbung hier falsch einzusetzen versuchst.

    Durch Vererbung drueckt man ja eine "ist-ein" Beziehung aus. Das heisst dass alle Eigenschaften der Superklasse auch auf die Kindklasse zutreffen.

    Wenn Du in deinem Beispiel eine Klasse MyNewClass1 von MyClass erben laesst, dann bedeutet das, dass MyNewClass1 eine List vom Typ MyClass besitzen muss. Nicht nur weil da der Compiler schreit, sondern weil Du sonst keine gueltige Vererbung mehr einsetzt.

    Eine List<MyNewClass1> ist restriktiver als eine List<MyClass>, also nicht vom gleichen Typ. Deshalb wuerde ich eher dazu raten das Design zu ueberdenken, anstatt einen Hack zu suchen, mit dem Du die Vererbung umgehen kannst.

    Vererbung sollte man ganz allgemein so selten wie nur moeglich einsetzen. In den meisten Faellen kann man Beziehungen genauso ueber Delegation ausdruecken. Und Delegation ist viel sicherer und verstaendlicher als Vererbung.

    lg, Benjamin Ferrari, bookworm.at

  • Stefan Kögl
    10
    Stefan Kögl
    Mitglied
    Reaktionen
    10
    Punkte
    1.010
    Beiträge
    199
    • 6. Januar 2009 um 10:24
    • #3

    Ich denke, ich verstehe sein Problem. Wenn er jetzt in MyNewClass1 Objekte aus seinem Vektor nehmen und damit arbeiten möchte erhält er nur eine Referenz auf MyClass-Objekte und muss sie erst manuell casten. Er kann sich dabei aber nicht mal sicher sein, dass es überhaupt MyNewClass1-Objekte sind.

    Ich hatte genau dieses Problem mal in einer C#-Anwendung und hab keine sinnvolle Lösung gefunden. Mein "Wunsch" wäre ja ein keyword analog zu this, dass man statt dem aktuellen Typ einsetzen kann. (Ich weiß schon, dass es this.getClass() gibt, aber ein Vector<this.getClass()> funktioniert ja verständlicher Weise nicht)

  • a9bejo
    21
    a9bejo
    Mitglied
    Reaktionen
    42
    Punkte
    4.697
    Beiträge
    913
    • 6. Januar 2009 um 11:34
    • #4
    Zitat von Stefan Kögl

    Ich denke, ich verstehe sein Problem.

    Sein Problem verstehe ich auch. Was ich meinte ist, dass er nicht versuchen sollte, das Problem technisch zu lösen, sondern indem er sein Design überdenkt.

    Wenn Steff100 eine technische Loesung fuer sein Problem findet, dann ist sein Ergebnis nicht mehr objektorientiert. Eine MyClass ist definiert als etwas, dann einen Vektor besitzt, in den jedes Objekt vom Typ MyClass reinpasst. Und einen solchen Vektor hätte MyNewClass1 nicht mehr. Das bedeutet MyNewClass1 ist kein MyClass, und darf deshalb auch nicht von MyClass erben.

    Java, und die Konstrukte, die hier verwendet werden (Klassen, Instanzvariablen, Typisierung etc), wurden aber für objektorientierte Programmierung designed. Wenn er diese Mechanismen jetzt zu umgehen versucht, dann wird er sich nicht nur mit dem Compiler Probleme kriegen - Sein Code wird auch schwerer zu lesen und von anderen Developern missinterpretiert. Denn jeder Programmierer der sich den Code anschaut wird davon ausgehen, dass jede Instanz von MyNewClass1 auch eine Instanz von MyClass ist.

    lg, Benjamin Ferrari, bookworm.at

    2 Mal editiert, zuletzt von a9bejo (6. Januar 2009 um 11:47)

  • Stefan Kögl
    10
    Stefan Kögl
    Mitglied
    Reaktionen
    10
    Punkte
    1.010
    Beiträge
    199
    • 6. Januar 2009 um 11:48
    • #5
    Zitat von a9bejo

    Denn jeder Programmierer der sich den Code anschaut wird davon ausgehen, dass jede Instanz von MyNewClass1 auch eine Instanz von MyClass ist.

    Das ist natürlich auch der Fall. Jede Instanz von MyClass bzw erbenden Klassen enthält auch Referenzen auf weitere MyClass-Objekte.

    Jedoch möchte er MyNewClass1 so einschränken, dass sie nur Referenzen auf Objekte vom Typ MyNewClass1 enthält, die ja wie gefordert von MyClass erben. Das ist keine (unerlaubte) Ausweitung der Vererbung sondern eine (imho gültige, teilweise auch sinnvolle) Einschränkung.

  • a9bejo
    21
    a9bejo
    Mitglied
    Reaktionen
    42
    Punkte
    4.697
    Beiträge
    913
    • 6. Januar 2009 um 11:59
    • #6
    Zitat


    Jedoch möchte er MyNewClass1 so einschränken, dass sie nur Referenzen auf Objekte vom Typ MyNewClass1 enthält,

    Diese Einschränkung gibt es aber ja in MyClass selber nicht. Also fehlt der Kindklasse eine Eigenschaft der Mutterklasse.

    Die Klasse MyClass ist definiert als "Eine Klasse die einen Vektor besitzt, in den jede Objektinstanz vom Typ MyClass reinpasst".

    Wenn MyNewClass1 jetzt den Vektor restriktiver macht, dann trifft diese Eigenschaft nicht mehr zu: Es kann nicht mehr jede beliebige Instanz von MyClass in den Vektor, sondern nur noch solche, die auch vom Typ MyNewClass1 sind.

    D.h. das MyNewClass1 keine Instanz von MyClass mehr ist.

    lg, Benjamin Ferrari, bookworm.at

  • Stefan Kögl
    10
    Stefan Kögl
    Mitglied
    Reaktionen
    10
    Punkte
    1.010
    Beiträge
    199
    • 6. Januar 2009 um 12:06
    • #7

    OK, da muss ich dir recht geben. Ich habe jetzt das Problem vom OP gedanklich mit meinem damaligen vermischt, in dem die Liste nach außen hin nur lesbar war.

    In diesem Fall würde ich den Satz so abändern:
    Die Klasse MyClass ist definiert als "Eine Klasse die einen Vektor besitzt, in dem jede Objektinstanz vom Typ MyClass ist".

    So würde die Definition ja nicht verletzt werden.

  • daff
    14
    daff
    Mitglied
    Reaktionen
    11
    Punkte
    2.021
    Beiträge
    386
    • 6. Januar 2009 um 12:21
    • #8
    Zitat von Stefan Kögl

    Das ist natürlich auch der Fall. Jede Instanz von MyClass bzw erbenden Klassen enthält auch Referenzen auf weitere MyClass-Objekte.

    Jedoch möchte er MyNewClass1 so einschränken, dass sie nur Referenzen auf Objekte vom Typ MyNewClass1 enthält, die ja wie gefordert von MyClass erben. Das ist keine (unerlaubte) Ausweitung der Vererbung sondern eine (imho gültige, teilweise auch sinnvolle) Einschränkung.

    Hier muss man sich eigentlich nur fragen, ob das Ersetzbarkeitsprinzip [1, 2] erfüllt ist: Kann eine Instanz von MyNewClass1 überall dort eingesetzt werden, wo eine Instanz von MyClass erwartet wird? Wenn ja, dann ist MyNewClass1 ein Untertyp von MyClass. Die Einschränkung, die du da einführen möchtest, würde MyNewClass1 die Eigenschaft "Untertyp von MyClass" absprechen: MyNewClass1 hätte nicht mehr dieselben Eigenschaften wie MyClass. Du würdest quasi den Untertyp allgemeiner machen, als den Obertyp, und das ist nicht erlaubt.

    Huh, nach zweimal Preview und dem Suchen der korrekten VL-OOP-Folien sehe ich, dass a9bejo wieder schneller war.

    [1] http://www.complang.tuwien.ac.at/franz/objektor…rt/oop07-02.pdf
    [2] http://de.wikipedia.org/wiki/Liskovsch…itutionsprinzip

    Restrain the specimen!

    Einmal editiert, zuletzt von daff (6. Januar 2009 um 12:23)

  • Plantschkuh!
    24
    Plantschkuh!
    Mitglied
    Reaktionen
    163
    Punkte
    6.173
    Beiträge
    1.181
    • 6. Januar 2009 um 12:48
    • #9
    Zitat von Steff100

    Wie kann ich hierbei mein Problem lösen??


    Kommt darauf an, was genau dein Problem ist. Oberflächlich betrachtet kann man sowas lösen, indem die Oberklasse generisch gemacht wird. In C++ geht das so:

    Code
    #include <vector>
    
    
    template <typename Foo>
    class FooBase
    {
    public:
        std::vector<Foo> myVector;
    };
    
    
    class MyClass: public FooBase<MyClass>
    {
    };
    
    
    class MyOtherClass: public FooBase<MyOtherClass>
    {
    };
    
    
    int main()
    {
        MyClass myClassInstance;
        MyClass myClassDummy;
        myClassInstance.myVector.push_back(myClassDummy); /* OK */
    
    
        MyOtherClass myOtherClassInstance;
        MyOtherClass myOtherClassDummy;
        myOtherClassInstance.myVector.push_back(myOtherClassDummy); /* OK */
    
    
     // myClassInstance.myVector.push_back(myOtherClassDummy); /* not OK */
    }
    Alles anzeigen


    (Die Namen sind nicht wie bei dir, aber du schaffst das schon :) ) Wenn du von den vererbten Klassen MyClass bzw. MyOtherClass aber weiter vererben willst, bekommst du dieselbe Anomalie. Möglicherweise läßt sie sich auf dieselbe Art umgehen. Im klassischen oberflächlichen Sinn ist das wohl tatsächlich nicht objektorientiert, aber wenn du die Lösung deines Problems so besser modellieren kannst, dann go for it.

    *plantsch*

  • a9bejo
    21
    a9bejo
    Mitglied
    Reaktionen
    42
    Punkte
    4.697
    Beiträge
    913
    • 6. Januar 2009 um 12:51
    • #10
    Zitat von Stefan Kögl


    In diesem Fall würde ich den Satz so abändern:
    Die Klasse MyClass ist definiert als "Eine Klasse die einen Vektor besitzt, in dem jede Objektinstanz vom Typ MyClass ist".

    So würde die Definition ja nicht verletzt werden.

    stimmt, und die Umsetzung dieser Definition in Java währe, das auch MyNewClass1 Instanzen einen Vektor vom Typ Vektor<MyClass> enthalten.

    lg, Benjamin Ferrari, bookworm.at

  • a9bejo
    21
    a9bejo
    Mitglied
    Reaktionen
    42
    Punkte
    4.697
    Beiträge
    913
    • 6. Januar 2009 um 13:27
    • #11
    Zitat von Plantschkuh!

    Kommt darauf an, was genau dein Problem ist. Oberflächlich betrachtet kann man sowas lösen, indem die Oberklasse generisch gemacht wird.

    Find ich besser: Ein anders Design (sinnvoller und auch OOP gerechter). Der Typ des Vektors wird ja jetzt nicht mehr in der Base Klasse festgelegt und dann im Kind geändert: Er wird nachträglich injiziert.

    Ich bin aber immer noch der Meinung, dass man wenn möglich ganz auf Vererbung verzichten sollte.

    lg, Benjamin Ferrari, bookworm.at

    3 Mal editiert, zuletzt von a9bejo (6. Januar 2009 um 13:34)

  • Steff100
    6
    Steff100
    Mitglied
    Punkte
    330
    Beiträge
    50
    • 6. Januar 2009 um 20:13
    • #12

    Tja, das hatte ich mir gedacht, dass ich hier wohl die Vererbung falsch verwende. Es ist halt hierbei das Problem, dass ich vom Typ des Vektors Methoden aufrufen möchte, die halt MyClass nicht besitzt und dadurch Probleme bereitet.

    Ich habe nun die Möglichkeit von Plantschkuh! hergenommen und die vererbende Klasse mit einem generischen Parameter versehen. Sieht jetzt folgendermaßen aus:

    Code
    public abstract class MyClass<T extends MyClass<T>> {
    
    
         protected Vector<T> myVector = new Vector<T>();
         .....
    
    
    }
    
    
    public class MyNewClass1 extends MyClass<MyNewClass1> {
    
    
         .....
    
    
    }
    Alles anzeigen

    Hierbei muss ich leider trotzdem einige Variablen casten, welche nicht überprüft werden, aber grundsätzlich wäre eine Vererbung um ursprünglichen Design nicht vorgesehen gewesen. Diese ergab sich leider in der Entwicklung der zusätzlichen Wünsche des Auftraggebers.

    Für OOP würd ich vermutlich jetzt vielleicht mehr, aber immer noch 100Pkt. fürs Bsp bekommen. :winking_face: Würd mich trotzdem interessieren, was ihr von diesem Konstrukt haltet.

    Zitat von a9bejo

    Ich bin aber immer noch der Meinung, dass man wenn möglich ganz auf Vererbung verzichten sollte.

    Das würde halt einen Zusatz von mehreren 100 Zeilen Code pro Klasse bedeutet, der 2 bis mehrmals kopiert werden müsste. Genau das wollte ich damit verhindern.

    2 Mal editiert, zuletzt von Steff100 (6. Januar 2009 um 20:24)

  • Maximilian Rupp 27. Dezember 2024 um 00:26

    Hat das Thema aus dem Forum Programmieren nach Entwicklung verschoben.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!

Benutzerkonto erstellen Anmelden

Rechtliches

Impressum

Datenschutzerklärung

  • Alles
  • Dieses Thema
  • Dieses Forum
  • Seiten
  • Forum
  • Lexikon
  • Erweiterte Suche
  • Deutsch
  • English
Zitat speichern