Äh ich weis jetzt nicht genau, was du meinst. In obrigen Code mach ich es so: Ein Object in den Properties muss ja in Initalize() manuell initalisiert werden. Dafür gibt es einen Befehl. Dieser merkt sich, wo das Object in der Structur ist (geht ja mit offsetof). Wenn jetzt clone oder dispose aufgerufen wird, weis er wo sich Objecte in den Properties sich befinden und behandelt diese entsprechend.NicTheQuick hat geschrieben:Nutzt du dann die Runtime Structures dafür?GPI hat geschrieben:>Macht dein clone() prinzipiell nur ein simples CopyStructure() oder steckt da mehr dahinter? Was ist z.B., wenn sich in der
>Objektstruktur weitere Objekte befinden, die ja tatsächlich nur als Pointer abgebildet werden?
Basis ist immer ein CopyStructure. Aber mein Code beachtet auch Objekte - in der Fassung oben muss man ihn aber immer manuell Initalisieren. Wie gesagt, wenn du an meine zweite Variante interesse hast, sag bescheid.
Achso. Wenn man bevor man die Methode überschreibt die alte sichert - ein Alias erstellt - dann kann man auf die alten Methoden einfach zugreifen. Ansonsten ist sie gnadenlos überschrieben.Auch, wenn man sie überschrieben hat? Das geht nämlich bei mir, weil für jede Basisklasse eine eigene vTable existiert.>Kann man auf die Methoden des Parents zugreifen?
logisch.
Parent und Child haben eigene vTables.
Bei mir müsste man beim Child mitDas geht schon. Angenommen man hat eine Klasse "Base" mit der Methode "test()", die ein "Debug 1" macht, und eine Klasse "Child", die "test()" mit "Debug 2" überschreibt, kann trotzdem "Child" aus jeder seiner Methoden mit "super()\test()" - oder falls weitere Parentklassen bestehen mit "super(Parent)\test()" - die überschriebenen Methoden nutzen. Wenn also innerhalb "Child" eine Methode "test2()" mit Inhalt "super()\test() : test()" existiert und diese von außen ausgerufen wird, werden beide Debug ausgegeben.>Können nicht überschriebene Methoden einer Parent-Klasse auf überschriebene Methoden von der Child-Klasse zugreifen?
Jup. Es gilt immer die vTable des Objekts. Und bei einen Child können die Einträge des Parents "überschrieben". Die einzelnen Methoden können ja nicht wählen welche vTable jetzt aktiv ist.
AliasMethod(test,test_parent)
die alte Methode sichern. Danach kann sie jederzeit verwendet werden. Finde ich persönlich auch eleganter. Wenn man eine Methode überschreibt, dann meist aus guten Grund.
Ich versteh jetzt kein WortIch fand das ganz praktisch, wenn man Klassen erstellen will, bei denen es keinen Sinn macht sie mit einem leeren Konstruktur zu initialisieren. Wie zum Beispiel eine BufferedStream-Klasse, die einen Datenstrom zusätzlich im Speicher puffern soll. Dieser muss man im Konstruktor ja einen UnbufferedStream übergeben, damit sie darauf aufsetzen kann.>Kann man den Standard-Konstruktor bei dir privat schalten, sodass man die Klasse selbst zwar nicht ableiten, aber über andere
>Konstruktoren instantiieren kann?
Geht nicht.

Wäre technisch kein Problem das einzufügen. Nur ist so eine Sache, ich möchte nicht für jedes Objekt einen Mutex automatisch erzeugen, auch wenn er überhaupt nicht gebraucht wird. Wobei mir da gerade was einfällt. Vielleicht komm ich ja morgen dazu.Ein Mutex ist bei mir pro Objekt immer gratis dabei. Nutzt man statt dem Schlüsselwort "Method" einfach "Synchronized" und entsprechend auch "SynchronizedReturn" und "EndSynchronized", kann man nie zwei "Synchronized"-Methoden gleichzeitig aufrufen. Hat man daneben noch normale Methoden, können dieser aber trotzdem von mehreren Threads gleichzeitig verarbeitet werden.>Kann man bei dir Methoden schreiben, die automatisch einen Per-Object-Mutex sperren?
Was genau meinst du hier? Also automatisch geht es nicht, aber du kannst natürlich ein "Mutex" in den Properties speichern und dann bei jeder Methode ein LockMutex(*self\mutex) und UnLockMutex(*self\mutex) einfügen. Den Mutex muss man bei der Methode Initalize() erzeugen und mit "Dispose()" zerstören.
Das ganze lehnt auch wieder an das "synchronized"-Schlüsselwort in Java an.
Wenn feststeht, dass die Klasse ein Child ist, kopier ich erstmal in die Child-Vtable die parent.Ich hab auch immer noch das Problem mit den vTables. Da muss man dann eben immer noch händisch ran. Das ist auch das einzige, wo bei mir bei Erstellen einer Kindklasse noch etwas zur Laufzeit geändert wird. Gibt man in der Kindklasse in der vTable zum Beispiel eine 0 statt des Pointers zur Methode ein, wird nach dem "EndClass" die 0 durch den Pointer aus der Parent-Klasse ersetzt.>Bis auf Punkt 1 geht bei mir zumindest mal alles und ich finde es sehr praktisch.![]()
Da hab ich lange rumgefummelt, bis ich das hingekriegt hab.
CopyMemory(parent_vtable,child_vtable,SizeOf(parent_interface))
Bei EndClass überprüfe ich, ob die vtable auch komplett ausgefüllt wurde, wenn nicht - weil bspw. eine Methode declariert aber nicht definiert wurde, breche ich das Programm mit einen end ziemlich abrupt ab. Die Überprüfung erfolgt aber nur mit eingeschalteten Debugger.
Die vTable fülle ich übrigens bei der Definition der Methoden. Deshalb müssen bei den obrigen Code auch die Methoden definiert sein, bevor man die Klasse nutzen kann. Bei meiner zweiten Variante hab ich das so gelöst, das in Deklarationsteil mit Gosub in den "Definitions"-Bereich gesprungen wird. (und natürlich, wenn der Programmzeiger zu den Definitionen kommt, wird mittels Goto über alle Definitionen gesprungen, damit nicht versehentlich nochmals versucht wird die vtable aufzubauen).
sieht verkürzt so aus
Code: Alles auswählen
Macro Method(ret,func,p1=,p2=,p3=,p4=,p5=,p6=,p7=,p8=,p9=,p10=) ;EndIndent
Declare.ret __currentClass()__Class__#func(*self.__currentClass()__Class__struc)
PokeI(__currentClass()__Class__functions+OffsetOf(__currentClass()\func ()),@__currentClass()__Class__#func ())
Procedure.ret __currentClass()__Class__#func(*self.__currentClass()__Class__struc) ;EndIndent
Übrigens: Niemand sagt, das in einer vtable nur Zeiger sein dürfen, ich hab da auch ein paar Integer-Daten gespeichert, die ich zur Verwaltung brauche. Den Eintrag sollte man dann aber auch entsprechend nennen, bspw. __SizeOf. Generell hab ich alles interne mit zwei __ beginnen lassen, damit ich mir da selbst nicht in die Quere komme.
Zeig doch mal deinen Code - mich würde interessieren, wie du so manches gelöst hast
