Interface in Structure benutzen

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

Interface in Structure benutzen

Beitrag von NicTheQuick »

Hallo Leute,

ich weiß nicht, ob es einige hier sowieso schon so machen, aber hier ist mal
ein Beispiel, wie man sein Interface in die entsprechende Structure einbaut,
damit man auf Structure-Element gleichermaßen gut zugreifen kann wie auf
die Interface-Procedures.

Code: Alles auswählen

Interface Bruch_I
  Set(zaehler.q, nenner.q)  ;#False, wenn nenner = 0
  Double.d()
  Kehrwert()                ;#False, wenn zaehler = 0
  Kuerzen()
  Str.s()
EndInterface

Structure Bruch
  *VTable
  I.Bruch_I
  
  zaehler.q
  nenner.q
EndStructure

Macro New(Struc)
  Struc#_New()
EndMacro

Procedure Bruch_New()
  Protected *bruch.Bruch
  
  *bruch = AllocateMemory(SizeOf(Bruch))
  If Not *bruch : ProcedureReturn #False : EndIf
  
  *bruch\VTable = ?Bruch_VTable
  *bruch\I = *bruch
  *bruch\zaehler = 0
  *bruch\nenner = 1
  
  ProcedureReturn *bruch
EndProcedure

Procedure Bruch_Set(*bruch.Bruch, zaehler.q, nenner.q)
  If nenner
    *bruch\zaehler = zaehler
    *bruch\nenner = nenner
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #False
EndProcedure

Procedure.d Bruch_Double(*bruch.Bruch)
  ProcedureReturn *bruch\zaehler / *bruch\nenner
EndProcedure

Procedure Bruch_Kehrwert(*bruch.Bruch)
  If *bruch\zaehler
    Swap *bruch\zaehler, *bruch\nenner
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #False
EndProcedure

Procedure Bruch_Kuerzen(*bruch.Bruch)
  Protected k.l = 0, t.q, a.q = *bruch\zaehler, b.q = *bruch\nenner
  
  If *bruch\zaehler = 0
    *bruch\nenner = 1
    ProcedureReturn
  EndIf
  
  If *bruch\nenner < 0
    *bruch\zaehler = -*bruch\zaehler
    *bruch\nenner = -*bruch\nenner
  EndIf
  
  a = *bruch\zaehler
  If a < 0 : a = -a : EndIf
  
  b = *bruch\nenner
  While Not (a & 1 Or b & 1)
    a >> 1
    b >> 1
    k + 1
  Wend
  
  If a & 1 : t = -b : Else : t = a : EndIf
  
  While t
    While Not t & 1
      t >> 1
    Wend
    If t > 0 : a = t : t - b : Else : b = -t : t + a : EndIf
  Wend
  a << k
  *bruch\zaehler / a
  *bruch\nenner / a
EndProcedure

Procedure.s Bruch_Str(*bruch.Bruch)
  ProcedureReturn StrQ(*bruch\zaehler) + "/" + StrQ(*bruch\nenner)
EndProcedure

DataSection
  Bruch_VTable:
    Data.l @Bruch_Set(), @Bruch_Double(), @Bruch_Kehrwert(), @Bruch_Kuerzen(), @Bruch_Str()
EndDataSection

*zahl.Bruch = new(Bruch)
*zahl\zaehler = 208
*zahl\nenner = 26

Debug *zahl\I\Str()

*zahl\I\Kuerzen()
Debug *zahl\I\Str()

*zahl\I\Kehrwert()
Debug *zahl\I\Str()
Debug *zahl\I\Double()
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag von Andreas_S »

Hättest du vil. einen simpleren Code? blick da nicht durch...
Also wie das interface jetzt auf die Proceduren zeigt...
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
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

Beitrag von NicTheQuick »

Die entscheidenden Zeilen befinden sich in 'Bruch_New()'. Dort wird der
Speicher für 'Bruch' reserviert und die Startwerte gesetzt. Dort weise ich
auch 'Bruch\I' den selben Pointer zu wie 'Bruch' selbst. Da aber 'Bruch\I' auf
das Interface verweist, kann man mit 'Bruch\I\Funktionname()' alle im
Interface stehenden Funktionen nutzen und ohne das 'I' auf die
Strukturelemente selbst zugreifen.

Das ist zwar nur wieder ein Trick dafür, dass es echte Klassen in PB nicht
gibt, aber es erleichtert einem die Arbeit, wenn man gerne mit Interfaces
arbeitet.
Benutzeravatar
mk-soft
Beiträge: 3856
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

@NicTheQuick,

Viel anders sieht es in mein OOP-PreCompiler auch nicht aus. http://www.purebasic.fr/german/viewtopi ... highlight=

Mit AllocateMemory(...) gibt es aber das Problem mit Speicherlecks bei verwendung von Strings.
Habe diese mit Linkedlist reallisiert. Siehe Ergebnis im Tempverzeichnis topfile.oop und bottomfile.oop nach den starten.

FF :wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
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

Beitrag von NicTheQuick »

Deswegen nutze ich für meine Strings immer meine Stringpointer-Include,
die irgendwo im Forum rumschwirrt und auch auf meiner Seite zu finden ist.

Hab mir übrigens auch schon ein Konzept für Klassen in PB überlegt und hab
irgendwie auch Lust eine Art Precompiler zu schreiben.
Antworten