Vererbung

Klassen, Objekte, Methoden, Instanzen

Moderator: Moderatoren

Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi,

ich porkel den Thread mal wieder in den Vordergrund. Es geht schließlich um Vererbung und dann darf man das ;-)

Ich darf doch nochmals davon ausgehen, das Membervars aus der Superklasse an die Unterklasse vererbt werden und darin auch erreichbar sind!? Hm, wo liegt da wieder mein Denkfehler?

Code: Alles auswählen


CLASS datenbank
      PROTECTED:
      EXPORTED:

      VAR id                                                                  // jeder       

      METHOD init
      METHOD felderleeren                           

ENDCLASS

METHOD datenbank:init()
       ::id                   := 0 
       ::aStruktur         := {}
RETURN self

METHOD datenbank:felderleeren()                                         
       LOCAL cField
       LOCAL nFcount
       LOCAL nI

       nFcount := LEN(::aStruktur)
       FOR nI := 1 TO nFcount                                                   // Durchlauf der einzelnen Felder der DB
           cField := ::aStruktur[nI,1]
           IF ::aStruktur[nI,2] = "N"
              ::&(cField) := 0
           ELSEIF ::aStruktur[nI,2] = "C"
              ::&(cField) := SPACE(::aStruktur[nI,3])
           ELSEIF ::aStruktur[nI,2] = "D"
              ::&(cFIELD) := CTOD("")
           ELSEIF ::aStruktur[nI,2] = "L"
              ::&(cField) := .F.
           ENDIF
       NEXT
RETURN self
****************************************************
****************************************************
CLASS mitarbeiter FROM datenbank
      EXPORTED:
// Feldvariablen in DB
      VAR name,;
          vorname,;
          persnr
      METHOD initvaria
ENDCLASS
********************************************************************************
METHOD mitarbeiter:initvaria()
// ACHTUNG: immer auf DAtum achten!!!
       ::aIndex     := {;
                        {"ID","STR(id,8,0)"},;
                        {"PNR","persnr"},;
                        {"NAME","UPPER(name)"};
                       }
       ::name                 := "ohne"                                         // pauschal vorbesetzt
       ::Vorname              := "ohne"                                         //  "         "
       ::persnr               := "9999"                                         //  "         "
RETURN self
************************************************************
********************************************************************************
METHOD mitarbeiter:erzeugestruktur()                                               // hier wird NUR die Datenbankstruktur erzeugt
// ACHTUNG: immer auf DAtum achten!!!
       ::aStruktur := {;
                       { "ID",        "N",  8, 0 },;
                       { "NAME",      "C", 15, 0 },;
                       { "VORNAME",   "C", 15, 0 },;
                       { "PERSNR",    "C",  4, 0 }; 
                      }

RETURN self
Die Methode felderleeren(), sollte doch eigentlich ohne Probleme laufen, wenn sie aufgerufen wird aus dem Objekte Mitarbeiter, also mit ::felderleeren().

Warum macht sie das nicht? Beim 1. Durchlauf ist die ID, die klappt noch, sobald aber die Memvar name drankommt, kommt die Fehlermeldung Membervariable nicht bekannt für dieses Objekt. Sobald ich die Methode felderleeren() aber so umändere, dann klappt es:

Code: Alles auswählen

METHOD datenbank:felderleeren()                                         
       LOCAL cField
       LOCAL nFcount
       LOCAL nI
       LOCAL objekt := self

       nFcount := LEN(::aStruktur)
       FOR nI := 1 TO nFcount                                                   // Durchlauf der einzelnen Felder der DB
           cField := ::aStruktur[nI,1]
           IF ::aStruktur[nI,2] = "N"
              objekt:&(cField) := 0
           ELSEIF ::aStruktur[nI,2] = "C"
              objekt:&(cField) := SPACE(::aStruktur[nI,3])
           ELSEIF ::aStruktur[nI,2] = "D"
              objekt:&(cFIELD) := CTOD("")
           ELSEIF ::aStruktur[nI,2] = "L"
              objekt:&(cField) := .F.
           ENDIF
       NEXT
RETURN self

Wo liegt denn jetzt schon wieder mein Denkfehler?
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Manfred,
abgesehen von Deiner pauschalen Aussage am Anfang
Manfred hat geschrieben:Ich darf doch nochmals davon ausgehen, das Membervars aus der Superklasse an die Unterklasse vererbt werden und darin auch erreichbar sind!?
hast Du keinen Denkfehler begangen.
Die von Dir getroffene Aussage ist zu pauschal und daher falsch (wenngleich in Deinem Beispiel richtig). Es gibt auch die Möglichkeit, Methoden und Membervariablen so zu deklarieren, dass sie nur in der Superklasse bekannt sind und nicht mit vererbt werden (s. HIDDEN).
In Deinem Fall kann ich Dich dahingehend trösten, dass ich genau über dieses Problem auch des öfteren gestolpert bin und dies nur ähnlich wie Du lösen konnte (also datenbank:&(cField) := .F. oder auch self:&(cField) := 0)
Das Problem liegt m.E. in dem ::&(-Konstrukt, mit dem der Compiler/Linker so seine Probleme zu haben scheint...

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi Martin,

das mit dem Hidden usw. ist bekannt, wird aber von mir nicht genutzt.

Dann geht das Beispiel mal zum Support...... vorher schaue ich aber noch mal nach, ob es schon einen PDR dafür gibt.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi,

wobei ich jetzt trotzdem wieder Kopfjucken bekomme.

Ich denke es muß objekt:&(cField) heißen?

hm, objekt:&cField klappt auch.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Au mann, Manfred - da hatte ich ja wirklich Tomaten vor den Augen!!!
::&(cField) läuft bei Dir auf einen Fehler, sobald die zweite Variable dran ist, da in Deiner Superklasse nur die erste Variable (ID) hinterlegt ist.
Die anderen drei kommen ja erst in der aktuellen Klasse hinzu!
Also: mit ::&( wird durch das Auflösen auf die Methoden und Variablen der Superklasse zugegriffen - und dort gibt es die anderen drei Variablen nicht! Die kommen erst in Deiner Klasse mitarbeiter hinzu!

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi Martin

das ist es ja. Ich dachte, ich kenne alles aus der Klasse..

Deine Sache habe ich jetzt nicht so ganz verstanden, warum....

Ich rufe aus dem Objekt mitarbeiter doch die Methode auf und dann sollte doch alles bekannt sein?
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Manfred,
ja - solange Du in der Methode felderleeren auf die Variablen in der Klasse mitarbeiter zugreifen würdest...

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi Martin,

also direkt, oder wie meinst Du das?

Also über das Makro, so wie gemacht, klappt es dann wohl nicht?
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Manfred,
Du hast zwar Deine Klassendefinition gezeigt, aber nirgendwo, wann und wie Du die methode felderleeren aufrufst!

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi Martin,

hatte ich geschrieben, aber hier nochmal explizit:
Die Methode felderleeren(), sollte doch eigentlich ohne Probleme laufen, wenn sie aufgerufen wird aus dem Objekte Mitarbeiter, also mit ::felderleeren().
Also, es ist so, dass sie innerhalb einer mitarbeitermethode aufgerufen wird. Also self:felderleeren(), bzw. ::felderleeren().

Und so sollte doch alles bekannt sein!?
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Manfred,
hatte ich überlesen, sorry!
Manfred hat geschrieben:Und so sollte doch alles bekannt sein!?
Ja - eigentlich schon...

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

naja, ich habe es mal zum Support geschickt, mal abwarten was von dort kommt.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Ha,

soll nochmal einer sagen, die reagieren nicht, oder sonstwas....
**********************************
Hallo Manfred,

ich glaube nicht, dass Du hier einen Denkfehler begehst. Ich kann in
Deinem Code keinen 'Cast' entdecken, sodass ich Dir spontan Recht
geben würde: die Methode :FelderLeeren() wird als geerbte Methode
gerufen. Konsequenterweise sollte der Zugriff auf Instanzvariable der
gleichen Hierarchieebene über Self also nicht beschränkt werden. Der
Work-Around, den Du gefunden hast bestätigt diese Sichtweise
eigentlich. Lass' mich trotzdem die Sache noch eingehender prüfen;
ich melde mich, sobald ich mehr weiß.

Schöne Grüße,
Till Warweg

**************************************
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Und weiter geht es...
***********************************************
Hallo Herr Kunz,

Wir hatten inzwischen Gelegenheit uns das Problem genauer anzuschauen
und auch zu klären, wie das Verhalten definiert ist.

Zunächst will ich festhalten, dass der Zugriff auf Instanzvariablen die in
abgeleiteten Klassen eingeführt werden nicht erlaubt ist.

Das widerspricht der Idee des objektorientierten Entwurfes.
Die OOP sieht aber vor, dass Basisklassen Methoden rufen, die erst in
abgeleiteten Klassen eingeführt werden.

Vorsicht: Sie können gegenwärtig über den Trick einer localen Variablen
self zuzuweisen auf Instanzvariablen der abgeleiteten Klasse zugreifen, ich
muss sie aber dringend bitten dies nicht zu tun. Dass das jetzt funktioniert
ist eher ein Seiteneffekt und kann mit einer späteren Xbase++ Version
"behoben" sein.

Es bleibt aber die Frage zu klären, was sie in ihrem konkreten Fall tun
müssen, um das gewünschte Verhalten zu erreichen. Sie wollen eine
generische Klasse mit Funktionalität implementieren, die dann von
abgeleiteten Klassen benutzt wird. Schauen sie sich bitte hierzu das angefügte
Beispiel (case1.zip) an. Es ist angelehnt an ihre ursprüngliche Idee und deklariert
auf der Basisklasse die Methoden setNoIvar() und getNoIvar() als deferred.

Die abgeleitete Klasse implementiert diese Methoden. Wenn nun die
Basisklasse die Zuweisung an die IVars macht, dann wird setNoIvar
der abgeleiteten Klasse gerufen, die dann den Wert an die IVar setzen
kann.

---------------------

Ich habe noch einen anderen Ansatz ausprobiert (case2.zip), welcher vermeidet den
Makro Operator zu benutzen. Hier werden die Werte in einem Array der
Basisklasse gehalten, genau so wie das Struktur Array gehalten wird.

Eine Access/Assign Methode sorgt dafür, dass ::aValue korrekt initialisiert
wird, wenn ::aStruktur gesetzt wird.
Wird einer IVar einer abgeleiteten Klasse ein Wert zugewiesen und ist diese IVAR
nicht deklariert, wird setNoIVar() der Basisklasse gerufen. Schauen sie sich
den Code doch einfach mal an.

Haben sie hierzu noch Fragen?

Mit freundlichen Grüssen,
Andreas Herdt
Alaska Technical Support
****************************************************
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Teil case1

Code: Alles auswählen

CLASS datenbank
      PROTECTED:
      EXPORTED:

VAR astruktur

      VAR id                                                                  // jeder

      DEFERRED METHOD setNoIvar
      DEFERRED METHOD getNoIvar

      METHOD init
      METHOD felderleeren

ENDCLASS

METHOD datenbank:init()
       ::id                   := 0
//       ::aStruktur         := {}
RETURN self

METHOD datenbank:felderleeren()
       LOCAL cField
       LOCAL nFcount
       LOCAL nI

       nFcount := LEN(::aStruktur)
       FOR nI := 1 TO nFcount                                                   // Durchlauf der einzelnen Felder der DB
           cField := ::aStruktur[nI,1]
           IF ::aStruktur[nI,2] = "N"
              ::&(cField) := 0
           ELSEIF ::aStruktur[nI,2] = "C"
              ::&(cField) := SPACE(::aStruktur[nI,3])
           ELSEIF ::aStruktur[nI,2] = "D"
              ::&(cFIELD) := CTOD("")
           ELSEIF ::aStruktur[nI,2] = "L"
              ::&(cField) := .F.
           ENDIF
       NEXT
RETURN self
****************************************************
****************************************************
CLASS mitarbeiter FROM datenbank
      EXPORTED:
// Feldvariablen in DB

      METHOD setNoIvar
      METHOD getNoIvar

      VAR _myname,;
          vorname,;
          persnr
      METHOD initvaria

      METHOD erzeugestruktur()
ENDCLASS
********************************************************************************
METHOD mitarbeiter:initvaria()
// ACHTUNG: immer auf DAtum achten!!!
       ::aIndex     := {;
                        {"ID","STR(id,8,0)"},;
                        {"PNR","persnr"},;
                        {"_myNAME","UPPER(name)"};
                       }
       ::_myname                 := "ohne"                                         // pauschal vorbesetzt
       ::Vorname              := "ohne"                                         //  "         "
       ::persnr               := "9999"                                         //  "         "
RETURN self
************************************************************
********************************************************************************
METHOD mitarbeiter:erzeugestruktur()                                               // hier wird NUR die Datenbankstruktur erzeugt
// ACHTUNG: immer auf DAtum achten!!!
       ::aStruktur := {;
                       { "ID",        "N",  8, 0 },;
                       { "_myNAME",      "C", 15, 0 },;
                       { "VORNAME",   "C", 15, 0 },;
                       { "PERSNR",    "C",  4, 0 };
                      }

RETURN self

METHOD mitarbeiter:setNoIvar( cName, xValue )
  ::&(cName) := xValue
RETURN self

METHOD mitarbeiter:getNoIvar( cName )
RETURN ::&(cName)

PROC main()


  o := mitarbeiter():new()
  o:erzeugestruktur()
  o:felderleeren()

RETURN

Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Teil2 case2

Code: Alles auswählen

CLASS datenbank
      HIDDEN:

      PROTECTED:
      EXPORTED:

      VAR aStrukt
      ACCESS ASSIGN METHOD setStruktur VAR aStruktur

      VAR aValues

      VAR id                                                                  // jeder

      METHOD setNoIvar
      METHOD getNoIvar

      METHOD init
      METHOD felderleeren

ENDCLASS

METHOD datenbank:setStruktur()

  IF PCount() == 0
    // ACCESS the IVAR
    RETURN AClone( ::aStruktur )
  ENDIF

  // ASSIGN the IVAR
  ::aStrukt := AClone( PValue(1) )
  ::aValues := Array( Len(::aStrukt) )

RETURN

METHOD datenbank:init()
       ::id                   := 0
//       ::aStruktur         := {}
RETURN self

METHOD setNoIvar( cMessage, xValue )
  LOCAL nPos
  nPos := AScan( ::aStrukt, {|s| Upper(s[1]) == Upper(cMessage) } )
  IF 0 == nPos
    Alert( "Feld " + cMessage + " unbekannt" )
    BREAK()
  ENDIF
  ::aValues[nPos] := xValue
RETURN self

METHOD getNoIvar( cMessage )
  LOCAL nPos
  nPos := AScan( ::aStrukt, {|s| Upper(s[1]) == Upper(cMessage) } )
  IF 0 == nPos
    Alert( "Feld " + cMessage + " unbekannt" )
    BREAK()
  ENDIF
RETURN ::aValues[nPos]

METHOD datenbank:felderleeren()
       LOCAL cField, cType, xValue
       LOCAL nFcount
       LOCAL nI

       nFcount := LEN(::aStrukt)
       FOR nI := 1 TO nFcount                                                   // Durchlauf der einzelnen Felder der DB
           cField := ::aStrukt[nI,1]
           cType  := ::aStrukt[nI,2]
           DO CASE
           CASE cType == "N"
             xValue := 0
           CASE cType == ""
             xValue := SPACE(::aStrukt[nI,3])
           CASE cType == ""
             xValue := CToD("")
           CASE cType == ""
             xValue := .F.
           ENDCASE
           ::setNoIvar( cField, xValue )
       NEXT
RETURN self
****************************************************
****************************************************
CLASS mitarbeiter FROM datenbank
      EXPORTED:
// Feldvariablen in DB

      METHOD initvaria

      METHOD erzeugestruktur()
ENDCLASS
********************************************************************************
METHOD mitarbeiter:initvaria()
// ACHTUNG: immer auf DAtum achten!!!

#ifdef ALASKA_REMOVED_CODE
       ::aIndex     := {;
                        {"ID","STR(id,8,0)"},;
                        {"PNR","persnr"},;
                        {"_myNAME","UPPER(name)"};
                       }
#endif

       ::_myname              := "ohne"                                         // pauschal vorbesetzt
       ::Vorname              := "ohne"                                         //  "         "
       ::persnr               := "9999"                                         //  "         "
RETURN self
************************************************************
********************************************************************************
METHOD mitarbeiter:erzeugestruktur()                                               // hier wird NUR die Datenbankstruktur erzeugt
// ACHTUNG: immer auf DAtum achten!!!
       ::aStruktur := {;
                       { "ID",        "N",  8, 0 },;
                       { "_myNAME",      "C", 15, 0 },;
                       { "VORNAME",   "C", 15, 0 },;
                       { "PERSNR",    "C",  4, 0 };
                      }

RETURN self


PROC main()


  o := mitarbeiter():new()
  o:erzeugestruktur()
  o:felderleeren()
  o:initvaria()

  ? o:_myName
  ? o:vorname
  ? o:persnr

RETURN
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Manfred,
vielen Dank für das Posting.
Aber hier verstehe ich was nicht:
Manfred hat geschrieben:Zunächst will ich festhalten, dass der Zugriff auf Instanzvariablen die in abgeleiteten Klassen eingeführt werden nicht erlaubt ist.

Das widerspricht der Idee des objektorientierten Entwurfes.
Ich kann doch logischerweise eine abgeleitete Klasse gegenüber der Superklasse erweitern! Was natürlich nicht geht, ist dann, in der Superklasse auf die in der Subklasse ergänzten Variablen zuzuweisen - aber das hast Du doch auch nicht gemacht, oder habe ich da wieder Tomaten auf den Augen??
Vielleicht kann mir die mal freundlicherweise jemand entfernen...

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi Martin,

im Moment muß ich auch passen. Ich habe die Antwort zwar wortmäßig verstanden, aber nicht technisch. Das muß ich mir nochmals alles auf der Zunge zergehen lassen. Vielleicht ja jemand hier im Forum entsprechende Butter, oder Oel, um es fließender zu machen?
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Robert
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 36
Registriert: Mo, 13. Feb 2006 12:47

Beitrag von Robert »

Martin Altmann hat geschrieben: Was natürlich nicht geht, ist dann, in der Superklasse auf die in der Subklasse ergänzten Variablen zuzuweisen - aber das hast Du doch auch nicht gemacht, oder habe ich da wieder Tomaten auf den Augen??
Also wenn ich das richtig sehe ist das schon so. Durch den Makrooperator ist es ja so, als wenn man direkt auf die Instanzvariable zugreift.

Ohne den &-Operator würde das ja dann in etwa so aussehen:

Code: Alles auswählen

CLASS datenbank
     EXPORTED:
            VAR id
            METHOD feldleeren
ENDCLASS

CLASS mitarbeiter FROM datenbank
     
       EXPORTED:
              VAR name, vorname, persnr

ENDCLASS

METHOD datenbank:feldleeren()
    // die ganze Schleife spare ich mir 

      ::id            := ... // geht
      ::name      :=  ... // geht nicht, da in Klasse datenbank nicht bekannt
      ::vorname := ...  // dito
RETURN  
Klasse mitarbeiter könnte eine Methode feldleeren haben, welche dann auf name und vorname zugreifen kann, oder halt so wie von alaska vorgeschlagen.
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Robert,
Robert hat geschrieben:Klasse mitarbeiter könnte eine Methode feldleeren haben, welche dann auf name und vorname zugreifen kann, oder halt so wie von alaska vorgeschlagen.
eben - und das macht Manfred ja (nach eigener Aussage)! Er ruft die Methode felderleeren der Klasse mitarbeiter auf!

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi,

bevor jetzt hier die "Keilerei" losgeht, bzw. ich etwas falsch verstehe, oder ihr:

Die Methode feldleeren() wird in der Superklasse definiert und an Mitarbeiter vererbt.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Manfred,
Manfred hat geschrieben:Die Methode feldleeren() wird in der Superklasse definiert und an Mitarbeiter vererbt.
... und dort aufgerufen (sagtest Du), oder?
Keilerei ist nicht, keine Sorge! Dafür bin ich im Moment zu vollgefressen... :D

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi Martin,

richtig,

mitarbeiter:feldleeren()

Anfangs hatte ich noch ein/das Objekt mit übergeben und damit gearbeitet, deshalb ist es mir nicht aufgefallen. (mitarbeiter:feldleeren(mitarbeiter))

Dann wurde in der Methode feldleeren() alles so gemacht:

Code: Alles auswählen

method datenbank:feldleeren(objekt)
            objekt:id := blahblah
            objekt:name := blahbla
            objekt:vorname:blahblah
return self
klar, das das klappte, da wurde ja das Objekt mit übergeben. Aber für mich war es logisch, dass es auch ohne den parameter klappen muß, weil ja alles vererbt wird.

Tja, was sage ich jetzt dazu? Nix verstanden, oder alles in den falschen Hals gekriegt, oder verkehrte Welt?
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21198
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hm,

ich habe mir die beiden Beispiele nochmals angeschaut. Soweit ich es jetzt sehe, sind beim 1. 2 Methoden dazu gekommen, die ich in JEDER Unterklasse definieren muß, sprich bei 100 Vererbungen = 2x100 Methoden dabei.

Beim 2. habe ich etliches mehr an Quellcode als bei meiner ursprünglichen Idee, als ich das Objekt als Parameter mitübergeben habe.

Eigentlich war mein Ansinnen (und ist es auch jetzt noch) möglichst wenig zu schreiben und damit möglichst viel zu erreichen. Das sehe ich bei keinem der beiden Beispiele. Also sind sie für misch persönlisch uninteressant.

Verbessert mich, wenn ich auf dem Holzweg wandeln sollte.

PS: Wobei ich jetzt auch nicht verstehe, warum es nicht ratsam ist, das Objekt in eine Var zu speichern und damit weiterzuarbeiten.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Robert
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 36
Registriert: Mo, 13. Feb 2006 12:47

Beitrag von Robert »

Manfred hat geschrieben:
Dann wurde in der Methode feldleeren() alles so gemacht:

Code: Alles auswählen

method datenbank:feldleeren(objekt)
            objekt:id := blahblah
            objekt:name := blahbla
            objekt:vorname:blahblah
return self
Hallo,

kann ja auch sein, dass ich da falsch liege, aber:

Du hast die Methode feldleeren in Datenbank definiert.
Jetzt erbt die Klasse Mitarbeiter von der Klasse Datenbank alle nicht-hidden Variablen und Methoden.

Du kannst also z.B. auf das Attribut id über mitarbeiter:id zugreifen.
Weiterhin steht dir auch die Methode feldleeren zur Verfügung. Da du in der Klasse mitarbeiter diese Methode nicht erneut definierst, geht der Aufruf eben an datenbank:feldleeren(). Und im Kontext der Klasse datenbank stehen die variablen name und vorname nunmal nicht zur verfügung.
Antworten