Announcement

Collapse
No announcement yet.

globaler Zugriff auf Prozeduren in einer Klasse

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

  • globaler Zugriff auf Prozeduren in einer Klasse

    Ich habe in meinem Form eine Listbox angelegt, die zu Troubleshooting-Zwecken und Ähnlichem von allen möglichen Stellen im Programm per AddItem(Text) Log-Einträge bekommt. Hierzu existiert eine Prozedur TForm1.LogMessage.
    Nun habe ich das Problem, dass in der Klasse TForm1 Routinen einer anderen Unit (eigene FileIO-Routinen) verwendet werden, die wiederum ebenfalls auf diese Logging-Prozedur zugreifen soll. Hierzu muss die Unit FileIO im uses-Statement Form1 enthalten. Da aber schon die Unit TForm1 im uses-Statement FileIO enthält, bekomme ich einen Fehler "zirkuläre Referenz".

    Leuchtet mir auch irgendwo ein, aber andererseits muss es doch möglich sein, eine Routine global gültig zu definieren und dann von überall her auch aufzurufen?

    Danke,

    -- Thilo

  • #2
    ich bin auch mal faul und kopiere einen Teil der Delphi Hilfe als Antwort:

    >>>>

    Wenn sich Units direkt oder indirekt gegenseitig referenzieren, werden sie als gegenseitig voneinander abhängig bezeichnet. Gegenseitige Abhängigkeiten sind zulässig, wenn keine zirkulären Pfade auftreten, die eine uses-Klausel im interface-Abschnitt einer Unit mit der uses-Klausel im interface-Abschnitt einer anderen Unit verbinden. Ausgehend vom interface-Abschnitt einer Unit darf es also nicht möglich sein, über die Referenzen in den uses-Klauseln in interface-Abschnitten anderer Units wieder zu dieser Ausgangsklausel zu gelangen. Damit eine Gruppe gegenseitiger Abhängigkeiten gültig ist, muß der Pfad jeder zirkulären Referenz über die uses-Klausel mindestens eines implementation-Abschnitts führen.

    Im einfachsten Fall mit zwei gegenseitig voneinander abhängigen Units bedeutet dies, daß die Units sich nicht gegenseitig in den uses-Klauseln der jeweiligen interface
    -Abschnitte referenzieren dürfen. Das folgende Beispiel führt also bei der Compilierung zu einem Fehler:

    unit Unit1;

    interface
    uses Unit2;
    ...
    unit Unit2;
    interface
    uses Unit1;
    ...

    Eine legale gegenseitige Referenzierung ist jedoch möglich, indem eine der Referenzen in den implementation-Abschnitt verschoben wird:

    unit Unit1;

    interface
    uses Unit2;
    ...
    unit Unit2;
    interface
    ...
    implementation
    uses Unit1;
    ...

    Um unzulässige zirkuläre Referenzen zu vermeiden, sollten Sie die Units möglichst in der uses-Klausel des implementation-Abschnitts angeben. Werden jedoch Bezeichner einer anderen Unit im interface-Abschnitt verwendet, muß die betreffende Unit in der uses-Klausel im interface-Abschnitt angegeben werden.

    <<<<

    Es ist wirklich wichtig in welchen Abschnitt, interface oder implementation, die entsprechende uses-Anweisung steht.

    Gruß

    Jose

    Comment


    • #3
      Prima, das sollte helfen! Allerdings weise ich den versteckten Hinweis RTFM strikt zurück :-) die Delphi-Hilfe ist wirklich ein Hohn im Vergleich zu anderen Paketen. Recht unstrukturiert, und der Umfang an Info zu einem konkreten Eintrag ist bei weitem nicht das, was dem Einsteiger wirklich hilft. Vielleicht sieht das ein Delphi-Profi anders, dem mag die Hilfe als Nachschlagewerk ausreichend sein.

      -- Thil

      Comment


      • #4
        Hi Thilo,
        eine Anmerkung noch.
        Spätestens bei dieser Fehlermeldung sollte man anfangen, über die Vermeidung derartiger Abhängigkeiten nachzudenken.
        Die LogInfo's haben eigentlich in Form1 nichts zu suchen.
        Entweder du machst eine eigene Unit für das Logging oder du bringst es in deiner FileIO mit unter.
        Da kannst du eine Variable FLogStrings vom Typ TStrings definieren und eine Function:
        AddLogInfo(Const AString: String); ...
        Im Initialization kommt rein:
        FLogStrings := TStringList.Create;
        Im Finalization:
        FLogStrings.SaveToFile...;
        FLogStrings.Free;
        Und schon ist das Logging von Form1 entkoppelt.
        Jetzt kannst du es sogar in anderen Projekten benutzen.<BR>
        Gruß, Fran

        Comment


        • #5
          Frank Reim schrieb:
          "Die LogInfo's haben eigentlich in Form1 nichts zu suchen."

          Wieso? Ich habe exakt ein Form, das stellt das komplette User Interface zur Verfügung. Dort soll auch eine Listbox zur Mitverfolgung aller Log Messages (und nicht nur von FileIO) sichtbar sein. Hier werden von ALLEN Teilen meiner Applikation Fortschritts/Fehler/Info-Messages angezeigt, somit macht es m.E. sehr wohl Sinn, diese Infos in Form1 unterzubringen.

          In C++ würde ich einfach in jedem Modul, in dem ich auf andere Funktionen zugreife, das eintsprechende .h-File includen, und dann einen Pointer auf mein Objekt mit der entsprechenden Funktion (hier die LOG-Funktion) zur Verfügung stellen.

          Mir sind Konzepte wie Encapsulation etc. von anderen objekt-orientierten Sprachen geläufig, habe aber als Delphi-Einsteiger noch Probleme, deren Umsetzung in Delphi mit meinen Vorstellungen meiner Applikation in Einklang zu bringen. Deswegen bin ich einerseits für jeden Kommentar dankbar, andererseits gebe ich aber auch solange keine Ruhe, bis mir der Kommentar auch einleuchtet :-)

          -- Thil

          Comment


          • #6
            Hi Thilo,
            ein Beispiel verdeutlicht, was ich meine:
            http://www.reim-edv.de/download/logging.zip
            Das Logging kennt kein Form.
            Programmlogik und Formulare sollten komplett getrennt werden.
            Dies ist nur ein einfaches Beispiel.
            Du kannst auch das Strings - Object der Klasse durch das deines Forms ersetzen. Dabei benötigst du nicht den Verweis auf die unit Form1.
            Du weist einfach mit LogManager.LogStrings := MeineListBox.Lines;
            dein Object zu.
            Und im nächsten Projekt bindest du einfach die Unit Logging mit ein, und Alles funktioniert, auch, wenn es kein Form1 gibt!
            Fran

            Comment


            • #7
              Beim Kompilieren Deines beispiels kriege ich den Fehler: "[Fataler Fehler] LogSample.dpr(7): F1026 Datei nicht gefunden: 'ExceptionLog.dcu'" in der Zeile "Logging in 'Logging.pas';" in LogSample. Ich habe daraufhin "uses ExceptionLog" auskommentiert, dann ließ es sich erzeugen.
              Im Moment verdaue ich gerade die Struktur Deines Beispiels, vielen Dank erst mal, ich lasse mit Sicherheit wieder (fragenderweise) von mir hören!

              -- Thil

              Comment


              • #8
                Ups...,
                vergess ich immer, dass ich Eurekalog einsetze.
                Einfach rausschmeißen ist OK.<BR>
                Gruß, Fran

                Comment


                • #9
                  To Frank:

                  So weit ich das sehe, arbeitest Du mit dem Trick, dass Du an den LogManager eine String-Liste (Memo1.Lines) übergibst, die dann vom LogManager gefüllt wird, dies aber erst, wenn man im Form den entsprechenden Button klickt. OK, das kriege ich hin, indem ich ApplyLogStrings direkt nach LogMessage aufrufe.

                  Ich stelle mir jedoch etwas Anderes vor: jede Stelle soll direkt und ohne User-Aktion, d.h. sofort sichtbar, in meine Listbox auf dem Form schreiben (Sichern in eine Datei ist übrigens hier nicht nötig). Wie gestalte ich Aufrufe an Logmanager aus einer anderen Unit, die Memo1.Lines nicht kennt? Wie bekommt der LogManager von einer beliebigen Unit die Referenz zu der String-Liste Deiner Memo1?

                  Ist es nicht einfacher, "irgendwie" meine ListBox "global" bekannt zu machen, und dann eben global und einfach und direkt die ListBox zu beschreiben?

                  -- Thil

                  Comment

                  Working...
                  X