Module oop und EnableClass

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Module oop und EnableClass

Beitrag von NicTheQuick »

Ich muss zwar noch ein bisschen Refactoring betreiben, aber bisher sieht meine Implementierung so aus: classes.zip
In fast jeder Datei ist ein Beispiel dabei. Außerdem testet CLASS_TEST.pb das komplette Konstrukt. Wenn es keine Ausgabe gibt, dann funktioniert alles so, wie es soll. Es sind aber noch nicht alle Testcases und Möglichkeiten darin enthalten. Ihr könnt aber auch gerne damit herumspielen.
Ich habe mittlerweile das händische Hinzufügen der VirtualTable auch entfernt.

Edit:
Achja, wenn man "DebugLevel 10" benutzt, dann sieht man auch noch die Aufrufhierarchie der Konstrukturen und der Destruktoren und wann 'AllocateStructure()' und 'FreeStructure()' benutzt wird.
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Module oop und EnableClass

Beitrag von GPI »

@nic
Wenn ich das richtig sehe, wenn ein Child auf eine MemberVariable von Parent zugreifen will, muss es auch super benutzen, oder?
Das man beim Macro auch einen Parameterblock übergeben kann, auf die Idee bin ich nicht gekommen - blöd dass man nicht da einen Parameter reineditieren kann. Aber gute Idee.

Und das man nach einen CreateMacro-Macro ein : setzen muss, damit es weitergeht, war mir auch neu.... Warum auch immer.

edit: Kleiner Tipp, wenn man mit Createmacro ein Macro mit () erzeugt, kann man es mit UndefineMacro ohne () wieder "löschen".
also:
CreateMacro(__currentClass(),ClassName) :
UndefineMacro __currentClass
Zuletzt geändert von GPI am 02.11.2015 17:42, insgesamt 1-mal geändert.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Module oop und EnableClass

Beitrag von NicTheQuick »

GPI hat geschrieben:@nic
Wenn ich das richtig sehe, wenn ein Child auf eine MemberVariable von Parent zugreifen will, muss es auch super benutzen, oder?
Ja. Nenn es einen Nachteil, aber ich finde es nicht schlimm, wenn alle Member-Variablen automatisch private sind, solange man nicht superm() benutzt oder einen Getter dafür schreibt.
Das man beim Macro auch einen Parameterblock übergeben kann, auf die Idee bin ich nicht gekommen - blöd dass man nicht da einen Parameter reineditieren kann. Aber gute Idee.
Mir war es egal, ob man das 'this' bei jeder Methode noch hinschreibt oder nicht. Bei einigen Programmiersprachen ist das sowieso standard. Siehe z.B. Python.
Und das man nach einen CreateMacro-Macro ein : setzen muss, damit es weitergeht, war mir auch neu.... Warum auch immer.
Anders wollte es irgendwie nicht. Hauptsache es geht. <)
Benutzeravatar
xXRobo_CubeXx
Beiträge: 120
Registriert: 12.06.2015 16:08
Computerausstattung: Version 5.41 LTS
Wohnort: Wohnort
Kontaktdaten:

Re: Module oop und EnableClass

Beitrag von xXRobo_CubeXx »

Achja, wenn man "DebugLevel 10" benutzt
Was tut es? Hört sich nützlich an :) aber was macht Debuglevel genau ?
Ja ich habe die Hilfe Seite gelsen aber die Beschreibung ist für mich nicht ausagekräftig genug und es gibt kein Code zum demonstrieren

Code: Alles auswählen


DebugLevel 2

Debug "hallo 1"

Debug "hallo 2"

Debug "hallo 3"

Debug "hallo 4"

Debug "hallo 5"

Debug "hallo 6"

Was kann man damit machen? Welchen Vorteil hat man? :)
Version 5.41 LTS :)
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Module oop und EnableClass

Beitrag von GPI »

probier mal

debug "testest",5

oder lies mal die Anleitung zu debug :)
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Module oop und EnableClass

Beitrag von NicTheQuick »

Das hat eigentlich nichts mit diesem Thread zu tun, aber dennoch eine kurz Erklärung:
Debug "Text" wird immer ausgegeben.
Debug "Text", LEVEL nur dann, wenn man vorher mindestens DebugLevel LEVEL oder höher hingeschrieben hab.
So kann man sich verschiedene Debug-Stufen bauen, um nur grob oder feingranularer zu debuggen. Möchtest du an vielen Stellen in deinem Programm reichlich Informationen über "Debug" ausspucken, empfiehlt es sich, dahinter immer einen Level anzugeben. Da kann man gerne hoch ansetzen, also z.B. 10. Wichtigeren "Debug"-Ausgaben gibt man dann kleinere Level, also 9 abwärts. Später kann man dann die unwichtigen Debugs einfach ausschalten, indem man DebugLevel 9 setzt, weil man dann die ganzen "Debug"s mit Level 10 nicht mehr sieht, sondern nur noch die wichtigeren ab Level 9 abwärts.
Benutzeravatar
xXRobo_CubeXx
Beiträge: 120
Registriert: 12.06.2015 16:08
Computerausstattung: Version 5.41 LTS
Wohnort: Wohnort
Kontaktdaten:

Re: Module oop und EnableClass

Beitrag von xXRobo_CubeXx »

Danke gpi und nicthequick :allright:
Jetzt hab ich es verstanden :)
Version 5.41 LTS :)
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Module oop und EnableClass

Beitrag von GPI »

NicTheQuick hat geschrieben:Ja. Nenn es einen Nachteil, aber ich finde es nicht schlimm, wenn alle Member-Variablen automatisch private sind, solange man nicht superm() benutzt oder einen Getter dafür schreibt.
Nenn es Charakter :)

Ich hatte mich nur gewundert, wie du es mit Super hingebracht hast und das erklärts.
Mir war es egal, ob man das 'this' bei jeder Methode noch hinschreibt oder nicht. Bei einigen Programmiersprachen ist das sowieso standard. Siehe z.B. Python.
Mir geht es auch etwas um die Überprüfung. Ich möchte halt so viele Probleme wie möglich abfangen.

Ich hab bei mir jetzt ein

Code: Alles auswählen

    CompilerIf Not Defined(*self,#PB_Variable)
      CompilerError "Missing 'This'!"
    CompilerEndIf    
beim Method-Macro eingefügt. *self wird mittels "This" in Parameterblock definiert. Fehlt es, läuft was schief -> Fehlermeldung beim compilen. Zwar kann ich die Position von This damit nicht überprüfen, aber immerhin ob es vorhanden ist.
Anders wollte es irgendwie nicht. Hauptsache es geht. <)
Imo ein Bug in PB. Übrigens: Das Leerzeichen vor den Doppelpunkt ist auch wichtig!

Ich hab jetzt meine Variante hier hochgeladen: http://game.gpihome.eu/PureBasic/oop.7z

Mittlerweile bin ich recht flexibel, was die Klassenerstellung angeht:

Code: Alles auswählen

DeclareClass (cChild [,cParent] )
  Get()
  Set()
  Properties
  value.i
  object.cIrgendwas
EndDeclareClass
[...]
Class (cChild [,options])
  InitalizeObject(object, cIrgendwas [,Arraysize] )
  Method (i, Initalize, (this,*initvalue) ); Konstruktor - ein Initalwert ist möglich
     MethodReturn  (xxx)
  EndMethod
 [....]
EndClass
oder

Code: Alles auswählen

DeclareClass (cChild [,cParent] )
  Get()
  Set()
EndDeclareClass
[...]
Class (cChild [,options])
  value.i
  object.cIrgendwas

  InitalizeObject(object, cIrgendwas [,Arraysize] )
  Method (i, Initalize, (this,*initvalue) ); Konstruktor - ein Initalwert ist möglich
     MethodReturn  (xxx)
  EndMethod
 [....]
EndClass
oder

Code: Alles auswählen

Interface  cChild [ extends cParent] 
  Get()
  Set()
EndInterface
InitalizeClass(cChild [,cParent] )
[...]
Class (cChild [,options])
  value.i
  object.cIrgendwas

  InitalizeObject(object, cIrgendwas [,Arraysize] )
  Method (i, Initalize, (this,*initvalue) ); Konstruktor - ein Initalwert ist möglich
     MethodReturn  (xxx)
  EndMethod
 [....]
EndClass
oder

Code: Alles auswählen

Interface  cChild [ extends cParent] 
  Get()
  Set()
EndInterface
InitalizeClassEx(cChild [,cParent] )
  value.i
  object.cIrgendwas
EndInitalizeClassEx
[...]
Class (cChild [,options])
  InitalizeObject(object, cIrgendwas [,Arraysize] )
  Method (i, Initalize, (this,*initvalue) ); Konstruktor - ein Initalwert ist möglich
     MethodReturn  (xxx)
  EndMethod
 [....]
EndClass
Warum? Wenn man die Autovervollständigung nutzen will, dann kommt man um Interface-Endinterface nicht drumherum. Das sieht zwar nicht mehr ganz so schön im Code aus, aber es funktioniert.
Normalerweise würde ich sagen, das die Member-Variable-Definition eigentlich zur Klassendefinition gehört. Das funktioniert auch normalerweise wunderbar, es gibt aber eine große Ausnahme: Module (dazu gleich).

Folgende Class-Options gibt es:
oop::#AutoMutex - Jede Methode der Klasse wird automatisch mittels Mutex umschlossen
oop::#NoCreation - Verbietet die Benutzung der Klasse. Ist für Dummy-Klassen gedacht, die man nur erstellt, damit man sie als Parent nutzt.
oop::#NoChild - Die Klasse kann nicht als Parent benutzt werden. Wozu das gut sein soll? Keine Ahnung, aber ich hab mir überlegt, was man alles als Option nutzen kann :)

Der große Vorteil meines Codes ist, das es Modul-unabhängig ist. Man kann Klassen vollständig in Module-EndModule einfügen und die Klasse ist dann vollständig drin versteckt. Man kann auch die Klassen in Declare-Bereich declarieren und in "Rumpf" dann definieren. Eine Benutzung von außerhalb ist dann auch möglich mit modulename::klasse. Es gibt nur ein Problem: Eine solche Klasse kann nur ein als Parent dienen, wenn auch die Variablen in Declarations-Bereich sind. Darum die ganzen Varianten bei der Erstellung.

Mit Define_Object, Global_Object, Static_Object, Protected_Object werden Objecte erzeugt, die automatisch bei _ProcedureReturn, _EndProcedure und _End zerstört werden. Neu ist, das man einen InitalWert (integer oder halt Pointer) mitgeben kann. Mehr sind leider mit meiner Methode, wie ich die Klassen verwalte, nicht möglich. Notfalls kann man ja einen Pointer auf eine Struktur mitgeben. Meine Methode hier ist, das ich einen Default-Konstruktor habe, der immer aufgerufen wird und unabhängig von der Klasse ist. Der Ruft dann auch die Klassen-Initalize-Methode auf, sofern definiert.

Das "new" heißt bei mir AllocateObject() - damit wird ein freies Objekt erzeugt, das man selber mit FreeObject() wieder freigeben muss. CloneObject ist ähnlich, nur wird eine 1:1-Kopie des Objects erstellt (oder Null, falls es fehlschlägt).

Ansonsten gibts noch das CheckClass, CopyObject, ResetObject. Name sollte Programm sein.

Ich hab viel Wert auf Debug-Möglichkeiten gelegt. So werden, wenn der Debugger läuft, sämtliche Objekte in einer Liste erfasst. Bei _End werden dann alle nicht korrekt freigegeben Objekte aufgelistet und wo sie erzeugt werden. Zudem kann man mit DebugObject eine Meldung ausgeben, die auch die Objekterstellungsposition enthält. Bei der Klassenerstellung wird zudem kontrolliert, ob wirklich zu jeder Methode auch definiert wurde. Das passiert leider erst zur Laufzeit.
Das ganze wird aber nur mit eingeschalteten Debugger integriert, ansonsten ist es zugunsten der Geschwindigkeit und Speichernutzung ausge-compilerif-ed.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Antworten