Announcement

Collapse
No announcement yet.

Polymorphie geht nicht

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Polymorphie geht nicht

    Hallöle, ich habe eine Frage zur Polymorphie unter Delphi. Ich versuchte (sinngemaß folgendes):<BR>
    Die Implementierung von Laufen habe ich aus Übersichtlichkeitsgründen erstmal weggelassen.<BR>

    <PRE>
    type
    TTier=class
    private
    public
    procedure laufen; virtual abstract;
    end;

    TKatze=class(TTier)
    private
    public
    procedure laufen; override;
    constructor Create;
    end;

    implementation

    procedure irgendwas;
    var
    Tier:TTier;
    begin
    TTier:=TKatze.Create;

    TTier.laufen; !!!! Hier bekomme ich einen abstrakten Fehler

    TTier.Free;
    end;
    </PRE>
    <BR>
    Mit (TTier as TKatze).laufen funktionert es, das ist dann doch aber keine Polymorphie mehr oder? Oder habe ich hier ein grundsätzliches Verständnisproblem?<BR>
    <BR>
    Vielen Dank schonmal für Eure Hilfe.<BR>

  • #2
    Hallo Manny<BR>
    das Problem liegt an deinem Schreibfehler, du musst statt der Klasse TTier die Variable Tier benutzen.<BR>
    <PRE>
    procedure irgendwas;
    var
    Tier:TTier;
    begin
    Tier:=TKatze.Create;
    Tier.laufen;
    Tier.Free;
    end;
    </PRE>
    <BR>
    Gruss Thoma

    Comment


    • #3
      Danke, aber das war jetzt meine eigene Blödheit, bei mir steht schon Tier im Quellcode und nicht TTier, ich habs hier mal aktualisiert.

      (Sowas passiert mir immer, wenn mich irgendwas um den Verstand bringt)

      <PRE>
      type
      TTier=class
      private
      public
      procedure laufen; virtual abstract;
      end;

      TKatze=class(TTier)
      private
      public
      procedure laufen; override;
      constructor Create;
      end;

      implementation

      procedure irgendwas;
      var
      Tier:TTier;
      begin
      Tier:=TKatze.Create;
      Tier.laufen; !!!! Hier bekomme ich einen abstrakten Fehler
      Tier.Free;
      end;
      </PRE&gt

      Comment


      • #4
        Hallo!<br>
        Hm, bei mir klappt das alles prima!<br>
        Kann der Fehler villeicht in der Implementierung von TKatze.create liegen?<br>
        Dein Minimalbeispiel habe ich ohne den Create Konstruktor mal umgesetzt und es läuft einwandfrei!<br>
        BYE BERN

        Comment


        • #5
          Danke Bernd, dein Hinweis hat mich stutzig gemacht und so habe ich es selbst nochmal probiert.

          Ich habe bei mir versucht die Prozedur laufen durch eine weitere Klasse durchzureichen, also TTier -> TKatze -> TSiamkatze und habe in jeder Klasse die Methode laufen mit virtual; abstract; weitergereicht. Das scheint aber gar nicht nötig zu sein.

          Ich habe jetzt also nur noch in TTier die Deklaration mit virtual abstract und in TSiamkatze die Implementierung per override.

          Warum kann ich denn jetzt trotzdem noch von TTier eine Instanz bilden, eigentlich ist es doch so, daß bei einem abstrakten Element in einer Klasse die ganze Klasse abstrakt ist, oder

          Comment


          • #6
            Hallo,
            auch wenn TTier eine abstrakte Klasse ist, so ist es doch dennoch möglich ein Objekt dieser Klasse zu erzeugen, da schließlich TTier auch von TObjekt abstammt und somit den Konstruktor create usw. besitzt, doch dies ist nicht ratsam, da abstrakte Klassen nur als Basis für weitere abgeleitete Klassen dienen.

            Gruss Alex

            Comment


            • #7
              <i>Ich habe bei mir versucht die Prozedur laufen durch eine weitere Klasse durchzureichen,
              also TTier -> TKatze -> TSiamkatze und habe in jeder Klasse die Methode laufen mit virtual; abstract; weitergereicht.
              Das scheint aber gar nicht nötig zu sein.</i><br>
              Wenn du das so machst, <b>verdeckst</b> du (AFAIK) die Methode aus der Basisklasse, d.h. TSiamKatze.Laufen überschreibt
              TKatze.Laufen, aber <b>nicht</b> TTier.Laufen. Eigentlich müsste der Compiler diesbezüglich eine Warnung ausgeben.
              Vielleicht könntest du TKatze.Laufen als <tt>override; abstract;</tt> deklarieren, wenn du es unbedingt explizit
              dastehen haben willst -- hab ich noch nie ausprobiert.
              <p>
              <i>Warum kann ich denn jetzt trotzdem noch von TTier eine Instanz bilden,</i><br>
              Auch hier kriegst du eine Compilerwarnung. (Ich hab nie begriffen, warum nur eine Warnung und keinen Fehler.)
              <p>
              <i>eigentlich ist es doch so, daß bei einem abstrakten Element in einer Klasse die ganze Klasse abstrakt ist, oder? </i><br>
              In C++ schon. ;-)
              <p>
              Ciao, Uli

              Comment


              • #8
                Ich denke nicht, dass bei einem abstrakten Element die ganze Klasse abstrakt ist, ich will nicht sagen das es sinnvoll ist, aber ich kann ja auch in die Klasse TTier ein feld einfügen, dann ist nicht die gesamte Klasse abstrakt, sondern nur die Methode. Anders sieht es bei einer Klasse aus, die nur abstrakte Methoden enthält, diese Klasse ist dann völlig abstrakt

                Comment


                • #9
                  Hallo!<br>
                  Wie wäre es mit einer/der Alternative?<br>
                  Statt einer abtrakten Klasse Interfaces!<br>
                  type ITier = interface<br>
                  procedure laufen;<br>
                  end;<br>
                  <br>
                  type TKatze = class ( TInterfacedObject, ITier )<br>
                  procedure laufen;<br>
                  end;<br>
                  <br>
                  Programm:<br>
                  var<br>
                  tier : ITier;<br>
                  begin<br>
                  Tier := TKatze.create;<br>
                  usw...<br>
                  <br>
                  Die Vorteile sind:<br>
                  Man kann auch anderen Obekten mal das "laufen" beibringen.<br>
                  Wenn mal ein andres Objekt statt TObject "Laufen" soll kann man leicht das Interface in die Deklaration aufnehmen.<br>
                  TReportKatze = class ( TQuickReport, ITier )<br>
                  <br>
                  Mehrfachvererbung!!! Man kann statt nur eines Interfaces auch mehrere Interfaces in die Deklaration einbinden.<br>
                  TBellendeKatze = class ( TObject, ITier, IBellendesDing )<br>
                  <br>
                  BYE BERN

                  Comment


                  • #10
                    Danke erstmal für eure Hilfe, endlich "laufen" die Viecher. Das mit den Interfaces werde ich mir sicher nochmal genauer angucken, habe bis jetzt noch nie gehört, daß man damit eine echte Mehrfachvererbung realisieren kann.

                    Eine Frage hätte ich noch, wenn ich meine gesammelten Klassen jetzt speichern möchte, würde sich doch RTTI anbieten, oder?
                    Allerdings ist mir nicht ganz klar, ob dann bestimmte Sichtbarkeiten der zu speichernden Elemente Vorraussetzung sind und wie das genau funktioniert. Hätte da jemand von euch einen Link oder ein paar Einstiegsinformationen?

                    Danke schonmal, ihr habt mir wirklich sehr geholfen

                    Comment


                    • #11
                      Hallo!<br>
                      Infos findest Du z.B: unter http://www.blong.com/Conferences/BorConUK98/DelphiRTTI/CB140.htm<br>
                      <br>
                      BYE BERN

                      Comment


                      • #12
                        Hallo!<br>
                        Nur zur Klarstellung::<br>
                        Interfaces sind nur ein Hilfsmittel um die Mehrfachvererbung zu simulieren.<br>
                        Interfaces beinhalten keine Implementierungen der deklarierten Funktionen (wie abstrakte Klassen)<br>
                        Die eigentliche Implementierung der Funktionen muß in der neuen Klasse erfolgen.<br>
                        Beispiel: <br>
                        TKatze kann laufen<br>
                        TBellendesDing kann bellen<br>
                        Echte Mehrfachvererbung wäre jetzt:<br>
                        TBellendeKatze = Class ( TKatze, TBellendesDing) <geht NICHT in Delphi<br>
                        Und man hätte ein Objekt das sofort bellen und laufen kann<br>
                        Mit Interfaces definiert man nur den Zugriff. Die Implementierung der Funktionen laufen und bellen muß man dann in der neuen Klasse selbst durchführen.<br>
                        BYE BERN

                        Comment


                        • #13
                          @Bernd So leuchtet mir die Sache mit den Interfaces ein. Haben diese denn besondere Nachteile? Im Moment erscheinen sie mir sinnvoller als abstrakte Klassen, mal abgesehen von ein wenig Übersichtlichkeit, wenn ich ein Interface für völlig unterschiedliche Klassen schreibe.

                          Das mit dem RTTI ist mir allerdings n bissel hoch im Moment, hast du nicht vielleicht ein kleines simples Beispiel, bei dem ein Objekt gespeichert wird. Ich bin mir einfach nicht sicher, wie sich das am besten realisieren läßt.

                          Ich möchte später in meinem Programm nur eine gespeicherte Datei laden und aus dieser dann alle nötigen Objekte erstellen.
                          Ich wäre zwar von Hand in der Lage die Datenhaltung zu schreiben, allerdings hatte ich irgendwo mal gelsen, daß sich soetwas (das Speichern von ganzen Objekten) mit RTTI sehr leicht bewerkstelligen läßt

                          Comment


                          • #14
                            Interfaces:<br>
                            Ich hab da noch einen "Vorteil". Ein TInterfacedObject muß nicht explizit freigegeben werden. Wenn der Gültigkeitsbereich der Variablen verlassen wird oder der letzte "Eigentümer" das Objekt verwirft wird es automatisch freigegeben.<br>
                            Die Technik rund um Interfaces wird auch im Bereich COM verwendet. Wenn man die Grundzüge mal drauf hat tut man sich mit COM erheblich leichter.(Ich zumindest)<br>
                            Sorry RTTI nutzen wir nicht. Unser System ist komplett als "Plug In" System realisiert. Die benötigten Objekte sind in einzelnen Packages enthalten, die von einer zentralen Instanz verwaltet werden und nur bei Bedarf geladen werden.<br>
                            Ich glaube (ohne es konkret zu wissen), dass die Funktionen RegisterClass UnRegisterClass irgendwie mit der RTTI zu tun haben. In einer ersten Version wurden bei uns die Zugriffe mit diesen beiden Funktionen realisiert.<br>
                            BYE BERN

                            Comment


                            • #15
                              Ich würde es aus einer leicht geänderten Sichtweise betrachten.<br>
                              OOP und Polymorphie sind Konzepte in der Softwareentwicklung. Objecte, Interfaces, abstrakte Klassen, virtuelle Methoden sind deren Instrumente. D.h. im fazit: Man kann Interfaces und deren Möglichkeiten im Zusammenhang mit Objecten sehr wohl auch zur Umsetzung von Polymorphen Objecten, Unions von Objecten und Garbage Colletions benutzen.<br> Es hängt eigentlich nur davon ab welchen Namen man dem Kind gibt, technisch gesehen ist es aber durchaus möglich und korrekt.<br>

                              Gruß Hage

                              Comment

                              Working...
                              X