Procedure vorhanden?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Olafmagne
Beiträge: 140
Registriert: 07.12.2017 17:30
Wohnort: Sete/Frankreich

Re: Procedure vorhanden?

Beitrag von Olafmagne »

Wenn ich etwas brauchbares basteln kann, kein Problem.
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
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Procedure vorhanden?

Beitrag von mk-soft »

Kleine Hilfe für den Anfang:
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
Benutzeravatar
Olafmagne
Beiträge: 140
Registriert: 07.12.2017 17:30
Wohnort: Sete/Frankreich

Re: Procedure vorhanden?

Beitrag von Olafmagne »

@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, :idea: 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, :bluescreen: bin kein Profi, aber wie oben schon gesagt, ich möchte es selber schaffen, um es selbst geschafft zu haben! :lamer: (klingt das logisch?)

Olaf
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Re: Procedure vorhanden?

Beitrag von SMaag »

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()
Benutzeravatar
Olafmagne
Beiträge: 140
Registriert: 07.12.2017 17:30
Wohnort: Sete/Frankreich

Re: Procedure vorhanden?

Beitrag von Olafmagne »

@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:

Code: Alles auswählen

NewMap replace.i()
Macro dq
  "
EndMacro 
Macro Overwrite(proc)
  : replace(dq#proc#dq)=@proc#()
EndMacro 
das an das ende der Function geschrieben wird

Code: Alles auswählen

Declare f1(a.i=0) Overwrite(f1)

Procedure f2(a.i)
  Debug "f2"
EndProcedure Overwrite(f2)
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
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Re: Procedure vorhanden?

Beitrag von SMaag »

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

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

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!
Benutzeravatar
Olafmagne
Beiträge: 140
Registriert: 07.12.2017 17:30
Wohnort: Sete/Frankreich

Re: Procedure vorhanden?

Beitrag von Olafmagne »

@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
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Re: Procedure vorhanden?

Beitrag von SMaag »

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!

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.
Benutzeravatar
Olafmagne
Beiträge: 140
Registriert: 07.12.2017 17:30
Wohnort: Sete/Frankreich

Re: Procedure vorhanden?

Beitrag von Olafmagne »

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.
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Re: Procedure vorhanden?

Beitrag von SMaag »

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!
Antworten