Dynamische Membervariablen erzeugen

Konzeptionelles, Technisches, Termine, Fragen zum Hersteller usw.

Moderator: Moderatoren

Antworten
Benutzeravatar
andreas
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1902
Registriert: Mi, 28. Sep 2005 10:53
Wohnort: Osnabrück
Hat sich bedankt: 4 Mal
Kontaktdaten:

Dynamische Membervariablen erzeugen

Beitrag von andreas »

Hallo Leute,

gibt es vielleicht eine Möglichkeit in einer vorhandenen Klasse dynamisch eine zusetzliche Variable zu erzeugen, damit ich die z.B. mit oTest:cTest ansprechen kann. Da in meinem Programm ständig die globalen Einstellun gen wachsen, die ich mit Public-Variablen deklarieren muss, wollte ich eine Standartklasse haben, die ich dynamisch erweitern kann, ohne jedes mal die Klasse anpassen zu müssen.
Eine Lösung für die Speicherung in einem Array in der Klasse habe ich schon, nur der Aufruf wie im oberen Beispiel gefällt mir besser.

Es sollte so funktionieren:

oTest:cTest := "Test"
? oTest:cTest

Wenn die Variable nicht existiert, muss die erzeugt werden.
Gruß,

Andreas
VIP der XUG Osnabrück
Benutzeravatar
andreas
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1902
Registriert: Mi, 28. Sep 2005 10:53
Wohnort: Osnabrück
Hat sich bedankt: 4 Mal
Kontaktdaten:

Beitrag von andreas »

Ergänzung!

Ich möchte nur eine Standartklasse haben, damit ich die Variablen unterschiedlich gruppieren kann, ohne dafür extra Klassen zu schreiben.
Gruß,

Andreas
VIP der XUG Osnabrück
olaf870
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 128
Registriert: Mi, 26. Okt 2005 18:41
Wohnort: Berlin
Kontaktdaten:

Beitrag von olaf870 »

Hallo Andreas,
so müßte es gehen:

Code: Alles auswählen

PROC MAIN ()
#include 'class.ch'
aMyGlobVarNames := {}
aMyGlobVar      := {}

// Hier addierst Du alle deine Vars in 2 Arrays
aadd( aMyGlobVarNames   , { "cTest", CLASS_EXPORTED } )     // {VarNamen, DESCRIPTOR }
aadd( aMyGlobVar        , "Test"                      )     //  Werte
        /*
        usw. bis zu letzten Var
        */
MyGlobVar := MyGlobVar( aMyGlobVarNames, aMyGlobVar )

// Dann hast Du, was Du willst:
? MyGlobVar:cText   // -> "Test"
RETURN
Hier noch die Funktion MyGlobVar():

Code: Alles auswählen

func MyGlobVar( aMyGlobVarNames, aMyGlobVar )
LOCAL II
        IF ClassObject( 'GlobVar' ) == NIL
            ClassCreate( 'GlobVar', , aMyGlobVarNames )     // Definieren der Class
        ENDIF
        MyGlobVar := ClassObject( 'GlobVar' ):new()         // Instanz erzeugen

        FOR ii:=1 TO Len( aMyGlobVar  )
            MyGlobVar:&(aMyGlobVarNames[ii,1]) := aMyGlobVar [ii, 2 ]       // Zuweisung der Werte
        NEXT
return GlobVar
Vor jeder Zuweisung oder Abfrage mußt Du allerdings sicherstellen, daß die betreffende MemberVar existiert, wenn nicht mußt Du MyGlobVar um diese Membervar ergänzen. Das kannst Du z.B. so vornehmen:

Code: Alles auswählen

FUNC  CheckMemberVar( MyGlobVar, cVarName )
LOCAL aMyGlobVar, aMyGlobVarName, aXppIVars, II

    IF !ismemberVar( MyGlobVar, cVarName )      //
        aMyGlobVar      := {}
        aMyGlobVarName  := {}
        aXppIVars := MyGlobVar:classDescribe( CLASS_DESCR_MEMBERS )

        FOR ii:=1 TO Len( aXppIvars )
            // Hier merst Du dir alle Vars der Class GlobVar
            aadd( aMyGlobVarNames, { aXppIvars[ii, CLASS_MEMBER_NAME ], CLASS_EXPORTED } )
            aadd( aMyGlobVar, GlobVar:&(aMyGlobVarNames[ii,1]) )
        NEXT

        // Und addierst deine neue Var hinzu:
        aadd( aMyGlobVarNames, { cVarName, CLASS_EXPORTED } ); aadd( aMyGlobVar     , NIL )

        ClassDestroy( GlobVar )             // Patz machen

        // Hier ist dann die neue Class mit einem neuen Member cVarName
        MyGlobVar := MyGlobVar( aMyGlobVarNames, aMyGlobVar )
    ENDIF
RETURN MyGlobVar
Ab Xbase 1.9 kannst Du auf CheckMemberVar() auch verzichten und diese direkt in die Class integrieren, da erfolglose Zugriffe und Zuweisungen an nicht existierende Membervars durch die (undokumentierten) Methoden

Code: Alles auswählen

      METHOD getNoIVar
      METHOD setNoIVar
abgefangen werden. Dort mußt Du dann - analog zu CheckMemerVar() entsprechende Massnahmen einleiten, so daß Zuweisungen an die Instanz dann tatsächlich so möglich wären wie Du es beschrieben hast - ohne Rücksicht auf Existenz oder Nichtexistenz einer Membervar.
Es wäre interessant, das mal auszuprobieren. Wenn Du also Zeit hast ...
Ich kann mir allerdings nur schwerlich Rahmenbedingungen vorstellen, bei denen dieser Ansatz zur Verwaltung globaler Variablen strategische Vorteile bringt. Was willst Du denn damit machen?

Gruß
Olaf870
Benutzeravatar
andreas
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1902
Registriert: Mi, 28. Sep 2005 10:53
Wohnort: Osnabrück
Hat sich bedankt: 4 Mal
Kontaktdaten:

Beitrag von andreas »

Hallo Olaf,

danke für die Antwort. Ich glaube aber, dass es hiermit für die 1.82 Version zu kompliziert wird und sich nicht lohnen würde. Ich muss dann vielleicht erstmal bei meiner Wörterbuchklasse bleiben.
Ich kann mir allerdings nur schwerlich Rahmenbedingungen vorstellen, bei denen dieser Ansatz zur Verwaltung globaler Variablen strategische Vorteile bringt. Was willst Du denn damit machen?
Ich habe unter einer Oberfläche alle irgendwann bei uns in der Firma eingesetzte Programme vereinigt. Das ist aber auch noch nicht alles. Das Programm wächst immer weiter. Dabei muss ich mehr für die standartisierung sorgen. Es gibt immer mehr Einstellungen, auf die ich von unterschiedliechen Modulen zugreifen muss. Dabei kann ich diese Einstellungen auch auf die Gruppen aufteilen. Damit es nicht so viele Public-Variablen gibt, dachte ich, dass es sinnvoll wäre, so eine Klasse zu erstellen, die alle Variablen einer gruppe erhält. Da es aber mehrere Gruppen gibt, wollte ich nicht für jede Gruppe eine Klasse schreiben und dachte an so eine Standart-Klasse. Dann habe ich eine Wörterbuchklasse geschrieben, wo die Variablen in einem Array aufbewahrt werden. Diese hat aber ein Nacteil: ich muss bei jedem Aufruf einer Get-Methode immer als Parameter den Namen der Variablen übergeben, was meiner Meinung nach die Grösse der EXE-Datei beeinflussen wird.
Wahrscheinlich muss ich doch einzelne Klassen einsetzen, um späteren Umstieg auf so eine Standart-Klasse zu erleichern.
Gruß,

Andreas
VIP der XUG Osnabrück
Antworten