Procedure vorhanden?
Re: Procedure vorhanden?
Wenn ich etwas brauchbares basteln kann, kein Problem.
Ich mache aber keine Versprechungen.
Ich mache aber keine Versprechungen.
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
OS=Linux Zorin
PureBasic 6.xx
Re: Procedure vorhanden?
Kleine Hilfe für den Anfang:
Kleiner OOP Kurs mit Purebasic
Einiges mir Macros gelöst ...
Modul BaseClass (Modul als Object)
Kleiner OOP Kurs mit Purebasic
Einiges mir Macros gelöst ...
Modul BaseClass (Modul als Object)
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Re: Procedure vorhanden?
@mk-soft
Erster Link war die Basis für meinen Einstieg in OOP, als Anleitung, wie Interfaces verwendet werden.
Auch einiges an Code war hilfreich, um das Initalisieren zu verstehen.
Allerdings habe ich bis jetzt das Ganze sehr einfach gehalten, da das für mich gerade richtig war.
Nun möchte ich 'über mich hinaus wachsen', und ein paar Dinge ausprobieren.
Der Code von dir war/ist sehr hilfreich und vor allem lehrreich! Dafür ein Danke!
Ich habe schon eine Idee,
wie ich Zu Überschreibende Functionen in der BaseClass markiere und in der SupClass identifiziere,
um das dann automatisch erledigen zu lassen.
Mal sehen ob ich das hinbekomme,
bin kein Profi, aber wie oben schon gesagt, ich möchte es selber schaffen, um es selbst geschafft zu haben!
(klingt das logisch?)
Olaf
Erster Link war die Basis für meinen Einstieg in OOP, als Anleitung, wie Interfaces verwendet werden.
Auch einiges an Code war hilfreich, um das Initalisieren zu verstehen.
Allerdings habe ich bis jetzt das Ganze sehr einfach gehalten, da das für mich gerade richtig war.
Nun möchte ich 'über mich hinaus wachsen', und ein paar Dinge ausprobieren.
Der Code von dir war/ist sehr hilfreich und vor allem lehrreich! Dafür ein Danke!
Ich habe schon eine Idee,

um das dann automatisch erledigen zu lassen.
Mal sehen ob ich das hinbekomme,


Olaf
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
OS=Linux Zorin
PureBasic 6.xx
Re: Procedure vorhanden?
solange die Parameter der Proceduren gleich sind, ist das überschreiben kein Problem!
Code: Alles auswählen
EnableExplicit
Prototype TestProc()
Runtime Procedure _TestProcParent()
Debug "TestProcParent"
EndProcedure
Procedure _TestProcChild()
Debug "TestProcChild"
EndProcedure
Define TestProc.TestProc
Debug IsRuntime("_TestProcParent()")
Debug IsRuntime("nix")
If IsRuntime("_TestProcParent()")
; If _TestProcParent is existing, overwrite it with TestProcChild
TestProc = @_TestProcChild()
Else
TestProc = @_TestProcParent()
EndIf
TestProc()
Re: Procedure vorhanden?
@SMaag
Das überschreiben war nicht das Problem, das habe ich schon gelöst.
Ich brauchte eine Möglichkeit , eine Proc auf existence 'abzufragen',
Pseudocode:
module x
delare xyz(sg) Overwrite
endmodule
module abc
declare xyz(sg)
if is Runtime("xyz") then vTable(super)=abc::xyz
End Pseudocode
Overwrite ist ein Macro:
das an das ende der Function geschrieben wird
Nun habe ich eine "Liste" mit allen zu Überschreibenden Functionen,
und auch wenn in der ChildClass eine gleiche Function existiert, nur wenn in der replace-Map, wird überschrieben!
Man könnte es auch andersherum machen und die "NichtÜberschreibbaren"markieren , das ist Geschmackssache
Olaf
Das überschreiben war nicht das Problem, das habe ich schon gelöst.
Ich brauchte eine Möglichkeit , eine Proc auf existence 'abzufragen',
Pseudocode:
module x
delare xyz(sg) Overwrite
endmodule
module abc
declare xyz(sg)
if is Runtime("xyz") then vTable(super)=abc::xyz
End Pseudocode
Overwrite ist ein Macro:
Code: Alles auswählen
NewMap replace.i()
Macro dq
"
EndMacro
Macro Overwrite(proc)
: replace(dq#proc#dq)=@proc#()
EndMacro
Code: Alles auswählen
Declare f1(a.i=0) Overwrite(f1)
Procedure f2(a.i)
Debug "f2"
EndProcedure Overwrite(f2)
und auch wenn in der ChildClass eine gleiche Function existiert, nur wenn in der replace-Map, wird überschrieben!
Man könnte es auch andersherum machen und die "NichtÜberschreibbaren"markieren , das ist Geschmackssache
Olaf
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
OS=Linux Zorin
PureBasic 6.xx
Re: Procedure vorhanden?
Jetzt muss ich doch nochmal nach dem Sinn Fragen, da ich glaube, dass das so mit Vererbung nicht geht!
Man hat eine BaseClass und dann davon abgeleitete Klassen. Einen Procedure-Pointer in der BaseClass zu überschreiben ist meiner Meinung nach Kontraproduktiv und wird zu Fehlern führen.
PseudoCode Beispiel
Wenn man nun für Overwrite den Pointer der Class Mensch() auf Doktor() verbiegt, so ruft man dann auch über die
Klasse Arbeiter() FullName aus Doktor auf, so dass der Arbeiter bei FullName einen Dr. vorgestellt bekommt!
Vererbung ist doch eigentlich die automatische Einbindung aller Methoden() der BaseClass.
Wenn ein Overwrite definiert wird, dann wird nur die Methode der BaseClass in der ChildClass nicht impelmentiert und
durch eine eigene ersetzt. Das hat aber nichts mit verbiegen der Pointer der BaseClass zu tun.
Korrigiert mich bitte, wenn ich das falsch sehe!
Man hat eine BaseClass und dann davon abgeleitete Klassen. Einen Procedure-Pointer in der BaseClass zu überschreiben ist meiner Meinung nach Kontraproduktiv und wird zu Fehlern führen.
PseudoCode Beispiel
Code: Alles auswählen
; BaseClass
Class Mensch()
Methode Name()
EndMethode
Methode Surname()
EndMethode
Methode FullName()
FullName = Name + Surname
EndMethode
EndClass
Class Arbeiter() Extends Mensch()
Methode xy()
EndMethode
EndClass
Class Doktor() Extends Mensch()
Methode FullName() Overwrite FullName()
FullName= "Dr. " + Name + " " + Surname
EndMethode
EndClass
Klasse Arbeiter() FullName aus Doktor auf, so dass der Arbeiter bei FullName einen Dr. vorgestellt bekommt!
Vererbung ist doch eigentlich die automatische Einbindung aller Methoden() der BaseClass.
Wenn ein Overwrite definiert wird, dann wird nur die Methode der BaseClass in der ChildClass nicht impelmentiert und
durch eine eigene ersetzt. Das hat aber nichts mit verbiegen der Pointer der BaseClass zu tun.
Korrigiert mich bitte, wenn ich das falsch sehe!
Re: Procedure vorhanden?
@SMaag:
Ok, hier erst einmal ein kleines Tutorial, damit wir von der Gleichen Sache reden
Kleiner OOP Kurs von mk-soft
Da sieht man dann, dass alle Methoden in einem Interface definiert sind und in eine vTable, ein Speicherbereich, in dem die Adressen der Methoden, in der Reihenfolge im Interface stehen
Vererbung:
Alle geerbten Methoden stehen immer, wie auch bei einer Structure, am Anfang, dann erst kommen die Neuern Einträge
Wenn ich also eine Methode Get() in der BaseClass habe und dann eine Get()-Methode in der ChildClass, da,, steht in der vTable die geerbte Get() und dann die Child-Get() weiter hinten! Selbst wenn der Compiler die doppelte Funktion nicht reklamiert, beim Aufrufen würde die erste passende Adr genommen, und das ist immer die der BaseClass, steht ja am Anfang!
Deshalb wird zum Überschreiben einfach der FuncionPointer der neuen Methode auf die Adr der Alten gelegt, die Adr der BaseFunction wird die der Childfunction. Jetzt ist nur die Childfunction sicht bar, die BaseFunction ist nicht mehr in der vTable
Siehe dir das Tut an, dann solltest du verstehen, was ich meine.
Die BaseClass wird NICHT geändert, sondern nur die ChildClass" Angepasst"
Olaf
Ok, hier erst einmal ein kleines Tutorial, damit wir von der Gleichen Sache reden
Kleiner OOP Kurs von mk-soft
Da sieht man dann, dass alle Methoden in einem Interface definiert sind und in eine vTable, ein Speicherbereich, in dem die Adressen der Methoden, in der Reihenfolge im Interface stehen
Vererbung:
Alle geerbten Methoden stehen immer, wie auch bei einer Structure, am Anfang, dann erst kommen die Neuern Einträge
Wenn ich also eine Methode Get() in der BaseClass habe und dann eine Get()-Methode in der ChildClass, da,, steht in der vTable die geerbte Get() und dann die Child-Get() weiter hinten! Selbst wenn der Compiler die doppelte Funktion nicht reklamiert, beim Aufrufen würde die erste passende Adr genommen, und das ist immer die der BaseClass, steht ja am Anfang!
Deshalb wird zum Überschreiben einfach der FuncionPointer der neuen Methode auf die Adr der Alten gelegt, die Adr der BaseFunction wird die der Childfunction. Jetzt ist nur die Childfunction sicht bar, die BaseFunction ist nicht mehr in der vTable
Siehe dir das Tut an, dann solltest du verstehen, was ich meine.
Die BaseClass wird NICHT geändert, sondern nur die ChildClass" Angepasst"
Olaf
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
OS=Linux Zorin
PureBasic 6.xx
Re: Procedure vorhanden?
ja, ich kenn die OOP Beispiele und kann das selbst auch programmieren.
So wie du das beschrieben hast, den Pointer in der ChildClass abändern, ist das korrekt!
Wenn da 2x die gleiche Methode drin ist, wird wohl der erste Pointer genommen, falls der Compiler das durchlässt!
Das sehe ich auch so, hab es aber nicht getestet.
Prinzipiell brauchst du den direkten Zugriff auf die VTables über die Klassen hinweg.
Das geht natürlich mit einer MAP und dem listen aller relevanten Methoden + irgendeinen IndexVerweis auf den VTable Eintrag.
Oder gleich die VTable in einem Array, statt DataSection
Ich hab dazu auch noch ne Idee, die ohne die Map auskommt und das Intellisense nutzt: Und zwar die Struktur der VTable öffentlich machen!
hier der Brainstorming Code, wich ich mir das vorstelle. Ist jetzt nicht in Modul und Interface verpackt, aber sollte reichen um das Prinzip zu zeigen!
So wie du das beschrieben hast, den Pointer in der ChildClass abändern, ist das korrekt!
Wenn da 2x die gleiche Methode drin ist, wird wohl der erste Pointer genommen, falls der Compiler das durchlässt!
Das sehe ich auch so, hab es aber nicht getestet.
Prinzipiell brauchst du den direkten Zugriff auf die VTables über die Klassen hinweg.
Das geht natürlich mit einer MAP und dem listen aller relevanten Methoden + irgendeinen IndexVerweis auf den VTable Eintrag.
Oder gleich die VTable in einem Array, statt DataSection
Ich hab dazu auch noch ne Idee, die ohne die Map auskommt und das Intellisense nutzt: Und zwar die Struktur der VTable öffentlich machen!
hier der Brainstorming Code, wich ich mir das vorstelle. Ist jetzt nicht in Modul und Interface verpackt, aber sollte reichen um das Prinzip zu zeigen!
Code: Alles auswählen
; Struktur die über die VTable gelegt wird
Structure TVTable
QueryInterface.i
Addref.i
Release.i
MethodeA.i
MethodeB.i
EndStructure
Define *VTable.TVTable
*VTable = ?VirtualMethodeTable
Procedure QueryInterface()
EndProcedure
Procedure AddRef()
EndProcedure
Procedure Release()
EndProcedure
Procedure MethodeA()
EndProcedure
Procedure MethodeB()
EndProcedure
DataSection ;
VirtualMethodeTable: ; Virtual Methode Table; vTable
Data.i @QueryInterface() ; iUnknown : AddressOf(QueryInterface())
Data.i @AddRef() ; iUnknown
Data.i @Release() ; iUnknown
; individual Class Methodes!
Data.i @MethodeA() ; AddressOf Methode1()
Data.i @MethodeB()
EndDataSection
Debug *VTable\MethodeA ; die beiden Werte sind
Debug @MethodeA() ; identisch und somit o.k.
Re: Procedure vorhanden?
Ok, da muss noch nachgebessert werden:
Die Methoden müssen in einem <Interface> definiert werden NICHT in der Structure
Der Grund:
Wenn du ein Object declarierst, wird das Object vom Type Interface sein.
In der Structure ist an ERSTER Stelle ein Zeiger auf die vTable(Tabelle mit den Adressen der Methoden in der Reihenfolge, in der sie im Interface stehen, gespeichert)
Dann erst kommen die Parameter!
Die Adressen der Methoden können entweder in einer DataSection stehen, oder einzeln in der richtigen Reihenfolge eingegeben werden.
Da das Object vom Type Interface ist, wird ein Aufruf zB a\Get(a) folgendes in veranlassen( Sehr Vereinfacht):
Die function wird in dem Interface gesucht, der Index ist dann der Index in der vTable, und dann wird die Function mit der gefundenen ADRESSE ausgeführt!
Es ist wichtig zu verstehen, dass sowohl Interface als auch Structure einen Datentype representieren, der ein Speicherbereich zugzwiesen wird.
in diesem Speicerbereich, dessen Adrzsse in der Variable <a>(siehe "zB") steht.
Anders als ein normaler Functionsaufruf wird heir in dem Interface die Function gesucht und nicht in der Functionstabelle, die der Compiler für's compilieren anlegt.
So, nun sollte das ganze hoffentlich etwas klarer sein.
Das Überschreiben ist also folgendes:
BaseClass hat Methode< Get()> : ChildClass hat auch Methode Get()!
Nun sollte ich , wenn ich von einer Class erben will wissen, welche Methoden diese hat, das heisst, wenn ich eine BaseClass-Methode überschreiben will,
dann darf diese Methode NICHT im ChildClass-Interface erscheinen, sondern die Adresse der Child-Methode wird in der vTable einfach en die Stelle der BaseClass-Methode gesetzt. Da die BaseClass eine eigene vTable hat, diese wird beim erben copiert!!, kann ein BaseClass-Object die BaseClass-Methode weiter nutzen, diese vTable wird NICHT verändert!!!!
In dieser Weise kann auch virtuelle Methoden definiert werden( Methoden, die in Base definiert, aber (nicht) implementiert ist:::(PureBasic wird Das bemäkeln weshalb diese Function einfach eine "LeerFunction" ist,also
Preocedure Virtuell()
EndProcedure
Was ich nun machen will ist das Markieren der Function als :
<Static> = Function KANN nicht Überschierben werden
<Abstract>=Function MUSS Überschierben werden
<Virtuell> = Function KANN Überschierben werde
Jede Function steht in einer zusätzlichen Liste, entweder ListStatic, ListAbstract oder ListVirtuell, Kann auch eine <Map> sein
und beim "Erben" wird dann je nach Liste entschieden, wie die ChildFunction gehandhabt wird.
Die Methoden müssen in einem <Interface> definiert werden NICHT in der Structure
Der Grund:
Wenn du ein Object declarierst, wird das Object vom Type Interface sein.
In der Structure ist an ERSTER Stelle ein Zeiger auf die vTable(Tabelle mit den Adressen der Methoden in der Reihenfolge, in der sie im Interface stehen, gespeichert)
Dann erst kommen die Parameter!
Die Adressen der Methoden können entweder in einer DataSection stehen, oder einzeln in der richtigen Reihenfolge eingegeben werden.
Da das Object vom Type Interface ist, wird ein Aufruf zB a\Get(a) folgendes in veranlassen( Sehr Vereinfacht):
Die function wird in dem Interface gesucht, der Index ist dann der Index in der vTable, und dann wird die Function mit der gefundenen ADRESSE ausgeführt!
Es ist wichtig zu verstehen, dass sowohl Interface als auch Structure einen Datentype representieren, der ein Speicherbereich zugzwiesen wird.
in diesem Speicerbereich, dessen Adrzsse in der Variable <a>(siehe "zB") steht.
Anders als ein normaler Functionsaufruf wird heir in dem Interface die Function gesucht und nicht in der Functionstabelle, die der Compiler für's compilieren anlegt.
So, nun sollte das ganze hoffentlich etwas klarer sein.
Das Überschreiben ist also folgendes:
BaseClass hat Methode< Get()> : ChildClass hat auch Methode Get()!
Nun sollte ich , wenn ich von einer Class erben will wissen, welche Methoden diese hat, das heisst, wenn ich eine BaseClass-Methode überschreiben will,
dann darf diese Methode NICHT im ChildClass-Interface erscheinen, sondern die Adresse der Child-Methode wird in der vTable einfach en die Stelle der BaseClass-Methode gesetzt. Da die BaseClass eine eigene vTable hat, diese wird beim erben copiert!!, kann ein BaseClass-Object die BaseClass-Methode weiter nutzen, diese vTable wird NICHT verändert!!!!
In dieser Weise kann auch virtuelle Methoden definiert werden( Methoden, die in Base definiert, aber (nicht) implementiert ist:::(PureBasic wird Das bemäkeln weshalb diese Function einfach eine "LeerFunction" ist,also
Preocedure Virtuell()
EndProcedure
Was ich nun machen will ist das Markieren der Function als :
<Static> = Function KANN nicht Überschierben werden
<Abstract>=Function MUSS Überschierben werden
<Virtuell> = Function KANN Überschierben werde
Jede Function steht in einer zusätzlichen Liste, entweder ListStatic, ListAbstract oder ListVirtuell, Kann auch eine <Map> sein
und beim "Erben" wird dann je nach Liste entschieden, wie die ChildFunction gehandhabt wird.
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
OS=Linux Zorin
PureBasic 6.xx
Re: Procedure vorhanden?
wir reden wahrscheinlich etwas aneinander vorbei. Wir verstehen es beide, haben aber einen andern Blick drauf!
Mich interessiert das auch und ich versuch mal einen lauffähigen DemocCode zu machen!
Die Structure, die man zusätzlich händisch anlegen muss, war nur dazu da, einen korrekten Zugriff auf die Methoden-Adressen zu erhalten, so
dass man sie einfach überschreiben kann. Das Beispiel zielte nur darauf, zu zeigen wie ich mir das vorstelle.
Ich hab aber schon festgestellt, dass man das gar nicht braucht.
Mit SizeOf(Interfacd()) und OffsetOf(Interface()) kommt man auch an die Daten, ohne die extra Struktur.
Frage:
Wieso muss man festlegen, welche Funktion man überschreiben kann und welche nicht!
Ich muss das in der abgeleiteten Klasse eh händisch programmieren was ich überschreiben will
Soviel muss ich als Programmierer sowieso entscheiden!
Wenn es automatisch gehen soll mit dem überschreiben, muss ich auch zumindest den Namen der Funktion in der BaseClass kennnen und muss
mich dafür entscheiden in der abgeleiteten Klasse den gleichen Namen zu verwenden und dann noch ein Overwrite dahintersetzen.
Automatisch ist aber viel komplizierter!
Wie gesagt, ich mach mal einen DemoCode, dann können wir vielleicht aus beiden Codes jeweils das beste rausziehen!
Mich interessiert das auch und ich versuch mal einen lauffähigen DemocCode zu machen!
Die Structure, die man zusätzlich händisch anlegen muss, war nur dazu da, einen korrekten Zugriff auf die Methoden-Adressen zu erhalten, so
dass man sie einfach überschreiben kann. Das Beispiel zielte nur darauf, zu zeigen wie ich mir das vorstelle.
Ich hab aber schon festgestellt, dass man das gar nicht braucht.
Mit SizeOf(Interfacd()) und OffsetOf(Interface()) kommt man auch an die Daten, ohne die extra Struktur.
Frage:
Wieso muss man festlegen, welche Funktion man überschreiben kann und welche nicht!
Ich muss das in der abgeleiteten Klasse eh händisch programmieren was ich überschreiben will
Soviel muss ich als Programmierer sowieso entscheiden!
Wenn es automatisch gehen soll mit dem überschreiben, muss ich auch zumindest den Namen der Funktion in der BaseClass kennnen und muss
mich dafür entscheiden in der abgeleiteten Klasse den gleichen Namen zu verwenden und dann noch ein Overwrite dahintersetzen.
Automatisch ist aber viel komplizierter!
Wie gesagt, ich mach mal einen DemoCode, dann können wir vielleicht aus beiden Codes jeweils das beste rausziehen!