Announcement

Collapse
No announcement yet.

interessanter Delphi 5 Fehler

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

  • interessanter Delphi 5 Fehler

    Ich habe ein neues Objekt definiert, das einen <bold>privaten</bold> Konstruktor hat. Die Idee dahinter ist das solche Objekte nur von einer Controller-Komponente erzeugt werden kann.<br>
    Nun hatte ich erwartet das Delphi eine Fehlermeldung bringt, wenn ich TPrivateObject.Create aufrufe. Leider wird aber stattdessen TObject.Create aufgerufen.<br>
    Mist. Das sollte doch wohl ein Fehler des Compilers sein.

  • #2
    Hallo Robert,<br>ich denke nicht, dass es sich hierbei um einen Fehler handelt. Im Gegenteil, das ist OOP ! Von aussen ist Dein privater Constructor nicht sichtbar ! Da Dein Objekt sicherlich von TObject abgeleitet ist, hat es die TObject.Create (public in TObject) Methode geeerbt. Deshalb muß der Compiler TObject.Create aufrufen. Alles Andere wäre ein Fehler.<br>Jens Schuman

    Comment


    • #3
      Hallo Jens,

      ich denke aber das der Compiler trotztdem mindestens eine Warning losschlagen müsste.<br>
      Es wird zwar eine Objekt angelegt, aber nicht richtig. All der Code, welcher im Konstruktor des TPrivateObject liegt wird ja nicht ausgeführt und damit ein nur halb-fertiges Objekt erzeugt.

      Ich denke mal Robert wird mit dem jetzigen OOP-Umfang von Pascal sein Objekt nicht in der gewünschten Art und Weise realisieren können. Dazu müsste er den public-Konstruktor von TObjekt in seiner Klasse verstecken können, was aber meines Wissens nicht geht.

      Als Vorschlag für Robert für eine andere Realisierung hätte ich folgendes:<br>
      Geh doch über Schnittstellen. Erstelle ein Interface, welches genau die Methoden bereitstellt, die du für dein TPrivateObject gedacht hast. Dann läßt Du deine TPrivateObject dieses Interface implementierung und legst auch die Deklaration deiner Klasse in den Implementation-Abschnitt

      Comment


      • #4
        Jens,<br>
        Ich halte das trotzdem fuer einen Fehler. Ich rufe ja explizit TPrivateObject.Create. Damit sollte erst einmal die Sichtbarkeitsregel greifen. Private = isnich. Mindestens eine Warning sollte herauskommen, schliesslich sind Konstruktoren ja implizit override.<br><br>
        Bernhard,<br>
        Gute Idee, aber vorerst habe ich keine Zeit fuer diese Umstellung

        Comment


        • #5
          Hm, eigentlich MUSS eine Warnung kommen, sowas wie "Warnung sichtbarkeit von constructor wurde geändert" oder so. Ansonsten ist das schon korrektes OOP so. Ein Entwickler der einen privaten constructor/ oder Methode definiert/überschreibt möchte erreichen das die normalen User die Funktionen der Mutterklasse nutzen müssen, für seinen zur Unit bezogenen internen Code möchte er aber zusätzliche initialisierungen des Objectes durchführen. D.h. ein privater constructor macht meistens nur sinn wenn man eine ganze Klassenbibliothek aufbaut und in den Mutterobjecten die Möglichkeit privater Konstruktoren in den Kindobjecten vorgesehen hat.<br>
          Der Vorschlag mit den Interfaces ist noch der beste, wobei ich selber immer ein bischen "trauig" bin zwei komplett unterschiedliche "OOP Konzepte" vermischen zu müssen. Öfters wird ein User dadurch mehr verwirrt als das er Vorteile sieht.

          Gruß Hage

          Comment


          • #6
            Hallo Robert,<br>wenn ich den constructor Create eines Objektes in den private Abschnitt (ausversehen) schiebe, gibt der mein D5 eine Warnung aus. Ungefähr: Create erhält geringere Sichtbarkeit ... .
            <br>Jens Schuman

            Comment


            • #7
              Richtig, diese Fehlermeldung meinte ich. D.h. der Compiler weisst sehr wohl auf dieses Problem hin.

              Gruß Hage

              Comment


              • #8
                Hallo Robert,<br>ich weiß ja nicht wie wichtig es ist, dass nur Controller-Komponenten Zugriff auf den Konstruktor haben dürfen. Wenn das nicht so wichtig ist, deklariere doch einfach einen zweiten constructor im public Teil und nenne diesen constructor CtrlCreate; In der Doku sagt Du dann, dass der "normale" Anwender diesen Konstruktor nicht verwenden soll.<br>Jens Schuman

                Comment


                • #9
                  Hallo Jens, hallo Hagen,

                  die Fehlermeldung kommt nur, wenn man den Constructor, der in der Klasse TComponent ist überschreibt (also als Vorgängerklasse TComponent nimmt). Dieser ist auch als virtueller Konstruktor definiert, so das dieser Überschreibbar ist und der Compiler damit merkt das sich die Sichtbarkeit ändert.

                  Wenn man als Basisklasse TObject nimmt und den Construktor davon überschreibt, so erscheint keine Fehlermeldung. Der Konstruktor von TObject ist <b>kein</b> Virtueller Konstruktor. Und hierbei hält sich der Compiler mit Warnings bedeckt.

                  @Robert. Würde es nicht gehen, das du als Basisklasse deiner Klasse statt TObject TComponent nimmst. Ist zwar etwas mehr Balast, aber Du hättest deinen versteckten Konstruktor (aber auch ein Warning!)

                  Comment


                  • #10
                    Jens, das ist die richtige Idee, aber andersrum. Mein privater Konstruktor bekommt einen anderen Namen und der public Create wirft eine exception. Ruft jetzt ein Benutzer TPrivateObject.Create dann fliegt ihm die exception um die Ohren. Nach dem Motto RTFM

                    Comment


                    • #11
                      oder

                      <pre>

                      type
                      TMyObject = class(TObject)
                      private
                      constructor RtlCreate;
                      public
                      constructor Create;
                      end;<br>

                      constructor TMyObject.RtlCreate;
                      // dein intern gültiger constructor
                      begin
                      inherited Create;
                      end;<br>

                      constructor TMyObject.Create;
                      begin
                      raise Exception.Create('Ein TMyObject kann nicht erstellt werden.');
                      end;<br>

                      </pre>

                      Gruß Hage

                      Comment


                      • #12
                        Ja, leck mich..., Robert Du warst 2 Minuten schneller :

                        Comment


                        • #13
                          Hallo Hagen,<br>wie soll ein Objekt, das außerhalb der Unit deklariert wurde an RtlCreate kommen? <br> Jens Schuman

                          Comment


                          • #14
                            Jens, das ist ja genau der Trick. Nur eine Controllerkomponente, die in der gleichen unit wie TMyObject steht, darf RtlCreate aufrufen.<br>
                            Damit erreiche ich das nur eine Instanz dieser Controllerkomponente TMyObjects erzeugen kann. Diese Instanz kann dann solche Objekte durchaus herausgeben, aber kein anderer kann sie erzeugen.<br>
                            Das Ganze verwende ich in meiner HID Komponente (fuer USB-Geraete). Die Controllerkomponente erstellt fuer jedes gepluggte HID-Geraet ein Objekt das das Geraet repraesentiert. Mit ein paar Verwaltungstricks funktioniert es wunderbar

                            Comment


                            • #15
                              Hagen, wenn Du die Hose so schnell runter hast wie ich die Zunge draussen... ;-

                              Comment

                              Working...
                              X