Seite 1 von 1
Name einer Instanzvariablen [erledigt]
Verfasst: So, 27. Apr 2014 10:54
von Dieter
Hallo,
Wenn ich eine Kasseninstanzvariable in der Form obj := meineKlasse:meineInstanzvariable habe, dann bekomme ich über obj:classname den String "meineKlasse" zurückgeliefert. Gibt es eine Möglichkeit auch den String "meineInstanzvariable" zu erhalten? In xbase habe ich bisher keine zugehörige Methode gefunden.
Re: Name einer Instanzvariablen
Verfasst: So, 27. Apr 2014 12:46
von georg
Hallo, Dieter -
schau doch mal in der Xbase++ Dokumentation unter Klassenreferenz bei Text- und GUI-Klassen die Klasse Abstract() an. :className() ist eine von Abstract() abgeleitete Methode.
Allerdings verstehe ich Deinen Ansatz nicht ...
Code: Alles auswählen
FUNCTION Main()
Local aPos, aSize
Local cTest
Local oXbp, obj
aPos := {10, 10}
aSize := {120, 30}
oXbp := XbpPushButton():new(, , aPos, aSize)
oXbp:caption := "Test"
oXbp:create()
obj := oXbp:caption
cTest := obj:className()
RETURN (.T.)
FUNCTION AppSys()
RETURN (.T.)
In meinem Beispiel wird das Programm bei der Zuweisung zu cTest abbrechen, denn obj enthält kein Objekt, sondern einen String, und der hat keine Methode :className().
Du bekommst nur dann keinen Fehler in Deinem Programm, wenn Du :meineInstanzvariable ein Objekt zugewiesen hast, aber dann bekommst Du den Klassennamen dieses Objekts, und nicht den von meineKlasse.
wird funktionieren.
Re: Name einer Instanzvariablen
Verfasst: Mo, 28. Apr 2014 10:27
von Dieter
Hallo Georg,
ich gebe dir Recht, dass bei einer Instanzvariable :caption, die nur eine String enthalten kann, es nicht sehr spannend ist, den String "caption" zu erhalten. Spannend wird es meiner Meinung nach, wenn die Instanzvariable selbst ein Objekt ist und der Name des Objektes in einer Klassenmethode weiter benötigt wird. Alle XbpParts werden in der Childlist ihres Parents mit dem Klassennamen und der Position in dem Childlist-Array referenziert.
Beispiel : {SleText, SleText, SleNum, SleText}
Bei Verwendung von Classcode repräsentiert das 1. Element dieser Childlist die Instanzvariable meineKlasse:sle1 und das 2. Element die Instanzvariable meineKlasse:sle2.
Ich suche also eine Methode oder Funktion, die "sle2" zurückliefert, wenn ich die Instanzvariable Z. B. über childlist[2] oder in der Form obj:=oxbp:Sle2 übergebe.
Re: Name einer Instanzvariablen
Verfasst: Mo, 28. Apr 2014 10:45
von Tom
o:ClassDescribe() liefert ein Array mit allen gewünschten Informationen zurück. Wie bei "Symbolinfo" kann man das im Bedarfsfall eingrenzen. Definitionen hierfür in CLASS.CH.
Re: Name einer Instanzvariablen
Verfasst: Mo, 28. Apr 2014 13:09
von Dieter
Hallo Tom,
ich habe mir :classdescribe() nochmals angesehen und sehe aber keine Möglichkeit , wie man hier eine Methode schreiben könnte, die bei Objektübergabe den Instanzvariablennamen liefert.
Ich kann lediglich die Position meiner Instanzvariablen im Rückgabe-Array von classDescribe() ermitteln.
ASCAN(odlg:classdescribe(3) , {|a| a[1]=="sle1eingabe"}) liefert z.B. 97
ASCAN(odlg:classdescribe(3) , {|a| a[1]=="sle2eingabe"}) liefert z.B. 123
Dass ich Instanzvariablen ::sle1eingabe oder ::sle2eingabe in meiner Klasse habe, das weiß ich natürlich immer.
Was ich suche sollte wie folgt funktionieren:
METHOD meineKlasse:getVarname(obj)
...
...
RETURN cVarname
Leider sind da nur die Pünktchen ... und keine Lösung in Sicht.
Ich möchte in Zukunft die sle-Instanzvariablen und die Datenbankfelder gleich benennen und die zugehörigen Speicher-, Plausi- und Undo-Methoden vereinheitlichen.
Re: Name einer Instanzvariablen
Verfasst: Mo, 28. Apr 2014 13:15
von georg
Hallo, Dieter -
Du kannst den Namen einer Instanzvariablen nicht aus der Variablen selbst ableiten.
Wenn die Instanzvariable ein Objekt enthält, dann kannst Du den Klassennamen des Objektes ermitteln, da es sich um ein Objekt handelt. Eine Instanzvariable an sich ist aber kein Objekt (da kannst Du mit :className() ran), sondern eine Variable.
Du kannst (theoretisch) mittels :classDescribe() die Namen der Instanzvariablen laden und diese in einem Loop auslesen und mit dem Inhalt der Instanzvariablen vergleichen. Wenn oObj und Inhalt übereinstimmen, besteht, die Möglichkeit, dass Du den gewünschten Namen gefunden hast (sofern nicht eine andere Instanzvariable den gleichen Inhalt hat).
Re: Name einer Instanzvariablen
Verfasst: Mo, 28. Apr 2014 13:18
von Tom
Ich verstehe, um ehrlich zu sein, nicht ganz, worauf Du hinauswillst. Aber vielleicht wäre Dir mit einer zusätzlichen Instanzvariablen (Array?) geholfen, die die konkreten Namen aller fraglichen Instanzvariablen enthält?
Re: Name einer Instanzvariablen
Verfasst: Mo, 28. Apr 2014 16:22
von brandelh
eine Instanzvariable kann kein Objekt SEIN, nur eines als Inhalt haben.
Re: Name einer Instanzvariablen
Verfasst: Mi, 30. Apr 2014 0:51
von Dieter
Hallo,
ich sehe dank eurer berechtigten Hinweise mittlerweile ein, dass ich um eine zusätzliche Instanzvariable :fieldname nicht herum komme.
Dass man zweimal einen fast identischen Variablennamen in eine Codezeile schreiben muß, hat mich etwas übermütig werden lassen.
Folgender Code erzeugt ein neues Control unter Einbeziehung der Instanzvariable ::vorname und der Field-Variablen adr->vorname
Code: Alles auswählen
oDlg:vorname := DKSleText():new()
oDlg:label2eingabe:addItem(1,oDlg:vorname,"adr->vorname")
In ::addItem passiert unter anderem folgendes:
Code: Alles auswählen
IF !EMPTY(cFieldname)
oXbp:fieldname := cFieldname
oXbp:killinputFocus := {|| oXbp:speichern(cFieldname,LSHARED)}
ENDIF
IF oXbp:isderivedFrom("XBPSLE") .OR. oXbp:isderivedFrom("XBPMLE")
AADD(self:setParent():editControls, oXbp)
ENDIF
Eine Speicherklasse sollte vorher an alle Sle- und Mle-Klassen weiter vererbt werden.
Code: Alles auswählen
CLASS speichern
EXPORTED:
VAR fieldname
METHOD speichern
ENDCLASS
METHOD speichern:speichern(cAliasFeld,lShared)
LOCAL cAliasAlt, nPos, i, lFlagData, lFlag:= FALSE
LOCAL cAlias, cFeld, oXbp:=self
IF !oXbp:changed .OR. EMPTY(cAliasFeld)
RETURN
ENDIF
DEFAULT lshared TO LSHARED
lFlagData := IF(ASCAN(symbolInfo(SYMBOL_CLASSFUNC),"DATA")>0,.t.,.f.) // wenn die Methode :DATA() im Klassencode enthalten
//cAliasFeld := self:fieldname //hier nicht
i:=AT("->",cAliasFeld)
cAlias := SUBSTR(cAliasFeld,1,i-1)
cFeld := SUBSTR(cAliasFeld,i+2)
cAliasAlt:= ALIAS()
DBSelectArea(cAlias)
nPos := FieldPos(cFeld)
IF lShared
FOR i := 1 TO 50
IF RLOCK()
lFlag := TRUE
LOOP
ENDIF
SLEEP(10)
NEXT
IF !lFlag
MsgBox("Speichern in "+cALIAS+" zur Zeit nicht möglich !","Achtung" )
RETURN
ENDIF
ENDIF
IF lFlagData
FieldPut(nPos,self:Data())
ELSE
FieldPut(nPos,self:getData())
ENDIF
IF lShared
UNLOCK
ENDIF
RETURN
Vielen Dank für die vielen Hinweise.
Re: Name einer Instanzvariablen
Verfasst: Mi, 30. Apr 2014 15:03
von AUGE_OHR
Dieter hat geschrieben:Ich kann lediglich die Position meiner Instanzvariablen im Rückgabe-Array von classDescribe() ermitteln.
ASCAN(odlg:classdescribe(3) , {|a| a[1]=="sle1eingabe"}) liefert z.B. 97
ASCAN(odlg:classdescribe(3) , {|a| a[1]=="sle2eingabe"}) liefert z.B. 123
es handelt sich um ein 2-Dim Array !
Code: Alles auswählen
#include "Class.ch"
#pragma Library( "XppUi2.lib" )
#define CRLF CHR(13)+CHR(10)
PROCEDURE Main
LOCAL oXbp
LOCAL oBrowse
oXbp := XbpDialog():new( AppDesktop(),, {10,10}, {200,200} )
oXbp:create()
oBrowse := MyBrowse():new( oXbp:DrawingArea):create()
SET ALTERNATE TO Dialog.txt
SET ALTERNATE ON
oBrowse:ShowClass()
RETURN
CLASS MyBrowse FROM XbpBrowse
EXPORTED:
INLINE METHOD ShowClass()
InsObject2(::XbpBrowse)
RETURN NIL
ENDCLASS
PROCEDURE InsObject2(oObj)
LOCAL aItem
LOCAL i,iMax
LOCAL j,jMax
LOCAL cName
LOCAL cAttr
LOCAL bSaveError, oError
bSaveError := ErrorBlock()
?"***************************************************************************"
? oObj:className()+CRLF+CRLF
?"***************************************************************************"
aItem := oObj:classDescribe(,CLASS_HIDDEN)
iMax := LEN(aItem)
FOR i := 1 TO iMax
jMax := LEN(aItem[i])
DO CASE
CASE i = CLASS_DESCR_CLASSNAME
? "CLASS_DESCR_CLASSNAME"
? Var2Char(aItem[i])+CRLF
CASE i = CLASS_DESCR_SUPERCLASSES
? "CLASS_DESCR_SUPERCLASSES"
FOR j := 1 TO jMax
? Var2Char(aItem[i][j])
NEXT
? CRLF
CASE i = CLASS_DESCR_MEMBERS
? "CLASS_DESCR_MEMBERS"
ASort( aItem[i] ,,,{|x,y| Upper( x[CLASS_MEMBER_NAME] ) < ;
Upper( y[CLASS_MEMBER_NAME] ) } )
FOR j := 1 TO jMax
DO CASE
CASE aItem[i][j][CLASS_MEMBER_ATTR] == VAR_ASSIGN_HIDDEN
cAttr := "H"
CASE aItem[i][j][CLASS_MEMBER_ATTR] == VAR_ASSIGN_PROTECTED
cAttr := "P"
CASE aItem[i][j][CLASS_MEMBER_ATTR] == VAR_ASSIGN_EXPORTED
cAttr := "X"
OTHERWISE
cAttr := Var2Char(aItem[i][j][CLASS_MEMBER_ATTR])
ENDCASE
cName := Var2Char(aItem[i][j][CLASS_MEMBER_NAME])
? cAttr,cName
ErrorBlock( {|e| Break(e)} )
BEGIN SEQUENCE // Index-Daten holen
?? " "
?? oObj:&(cName)
RECOVER USING oError
ErrorBlock( bSaveError )
?? " ***"
END SEQUENCE
ErrorBlock( bSaveError ) // Alten Fehler-Codeblock
NEXT
? CRLF
CASE i = CLASS_DESCR_METHODS
? "CLASS_DESCR_METHODS"
ASort( aItem[i] ,,,{|x,y| Upper( x[CLASS_METHOD_NAME] ) < ;
Upper( y[CLASS_METHOD_NAME] ) } )
FOR j := 1 TO jMax
DO CASE
CASE aItem[i][j][CLASS_METHOD_ATTR] == VAR_ASSIGN_HIDDEN
cAttr := "H"
CASE aItem[i][j][CLASS_METHOD_ATTR] == VAR_ASSIGN_PROTECTED
cAttr := "P"
CASE aItem[i][j][CLASS_METHOD_ATTR] == VAR_ASSIGN_EXPORTED
cAttr := "X"
OTHERWISE
cAttr := Var2Char(aItem[i][j][CLASS_METHOD_ATTR] )
ENDCASE
cName := Var2Char(aItem[i][j][CLASS_METHOD_NAME] )
? cAttr,cName
NEXT
? CRLF
ENDCASE
NEXT
RETURN
*
*eof
*
Re: Name einer Instanzvariablen
Verfasst: Mi, 30. Apr 2014 17:58
von Dieter
Hallo Jimmy,
du schreibst:
es handelt sich um ein 2-Dim Array !
Das ist mir schon klar. Hilft aber überhaupt nicht, da in der Instanzvariable nur ein Zeiger auf ein Objekt gespeichert wird, welches somit nicht weiß, das es eine Instanzvariable gibt, die den Zeiger auf sich selbst enthält. Der Name der Instanzvariablen ist somit aus dem Objekt nicht ableitbar. Ich bitte deshalb meine blödsinnige Fragestellung in meinem Posting zu entschuldigen!