Einerseits wollte ich gern ein interessantes Projekt beginnen, andererseits möchte ich das Rad nicht neu erfinden:
Es geht um die objektorientierte Programmierung in PureBasic - soweit diese möglich ist.
Realisieren tut man das ja über Interfaces und, wenn man möchte, Modules, so jedenfalls beschreiben es die Sample codes unten.
Mein Ziel war es, für alle Bibliotheken in PureBasic Include-Dateien zu schreiben, die objektorientierten Zugriff auf die Funktionalitäten dieser ermöglichen. Wie das aussehen könnte, zeigen die Beispielcodes, in denen einmal die String-, Window- und Gadget-libraries auf's Korn genommen werden.
Nun sagte ich "das Rad nicht neu erfinden". Gibt es soetwas denn schon?
PHOENIX war der Name, den Frederix Laboreur ursprünglich für PureBasic vorgesehen hatte und er würde auch passen - PureBasic braucht vielleicht einen kleinen Hype, um aus der Asche neu zu entstehen. Ob das klappt? ; )
Zusätzlich zu den Bibliotheken könnte man eine eigene IDE schreiben, die über einen Precompiler auch einen etwas anderen Sytax ermöglicht. Ob das Sinn machen könnte, würde ich hier auch gern diskutieren.
Hier ein paar verkürzte Beispieldateien, die den objektorientierten Zugriff auf PB-Bibliotheken demonstrieren:
Code: Alles auswählen
;
; Window.pbi
Interface Window
BindEvent (Event, *Callback, Object = #PB_All, EventType = #PB_All)
Close ()
Delete ()
EndInterface
DeclareModule Window
Declare Event__Bind (Event, *Callback, Window = #PB_All, Object = #PB_All, EventType = #PB_All)
Declare Close (Window)
Declare Event__Gadget ()
Declare New (Window, x, y, InnerWidth, InnerHeight, Title$, Flags = #Null, ParentWindowID = #Null)
Declare WaitEvent (Timeout = #Null)
EndDeclareModule
Module Window
Structure SWindow
*VTABLE
Window. i
EndStructure
Procedure Event__Bind (Event, *Callback, Window = #PB_All, Object = #PB_All, EventType = #PB_All)
BindEvent (Event, *Callback, Window, Object, EventType)
EndProcedure
Procedure IEvent__Bind (*this. SWindow, Event, *Callback, Object = #PB_All, EventType = #PB_All)
BindEvent (Event, *Callback, *this \ Window, Object, EventType)
EndProcedure
Procedure Event__Gadget ()
ProcedureReturn EventGadget ()
EndProcedure
Procedure Close (Window)
CloseWindow (Window)
EndProcedure
Procedure IClose (*this. SWindow)
CloseWindow (*this \ Window)
EndProcedure
Procedure IDelete (*this. SWindow)
If IsWindow (*this \ Window)
CloseWindow (*this \ Window)
EndIf
FreeMemory (*this)
EndProcedure
Procedure New (Window, x, y, InnerWidth, InnerHeight, Title$, Flags = #Null, ParentWindowID = #Null)
Protected *this. SWindow
*this = AllocateMemory (SizeOf (SWindow))
If *this
*this \ VTABLE = ? VTABLE_SWindow
*this \ Window = OpenWindow (Window, x, y, InnerWidth, InnerHeight, Title$, Flags, ParentWindowID)
ProcedureReturn *this
EndIf
EndProcedure
Procedure WaitEvent (Timeout = #Null)
ProcedureReturn WaitWindowEvent (Timeout)
EndProcedure
DataSection
VTABLE_SWindow:
Data. i @ IEvent__Bind ()
Data. i @ IClose ()
Data. i @ IDelete ()
EndDataSection
EndModule
Code: Alles auswählen
;
; Gadget.pbi
Interface Gadget
Delete ()
Gadget ()
GetText. s ()
SetText (Text$)
EndInterface
DeclareModule Gadget
Declare Button (Gadget, x, y, Width, Height, Text$, Flags = #Null)
Declare NewButton (Gadget, x, y, Width, Height, Text$, Flags = #Null)
Declare$ GetText (Gadget)
Declare SetText (Gadget, Text$)
Declare String (Gadget, x, y, Width, Height, Content$, Flags = #Null)
Declare NewString (Gadget, x, y, Width, Height, Content$, Flags = #Null)
Declare Text (Gadget, x, y, Width, Height, Text$, Flags = #Null)
Declare NewText (Gadget, x, y, Width, Height, Text$, Flags = #Null)
EndDeclareModule
Module Gadget
Structure SGadget
*VTABLE
Gadget. i
EndStructure
Procedure Button (Gadget, x, y, Width, Height, Text$, Flags = #Null)
ProcedureReturn ButtonGadget (Gadget, x, y, Width, Height, Text$, Flags)
EndProcedure
Procedure NewButton (Gadget, x, y, Width, Height, Text$, Flags = #Null)
Protected *this. SGadget
*this = AllocateMemory (SizeOf (SGadget))
If *this
*this \ VTABLE = ? VTABLE_SGadget
*this \ Gadget = ButtonGadget (Gadget, x, y, Width, Height, Text$, Flags)
ProcedureReturn *this
EndIf
EndProcedure
Procedure IDelete (*this. SGadget)
FreeStructure (*this)
EndProcedure
Procedure IGadget (*this. SGadget)
ProcedureReturn *this \ Gadget
EndProcedure
Procedure$ GetText (Gadget)
ProcedureReturn GetGadgetText (Gadget)
EndProcedure
Procedure$ IGetText (*this. SGadget)
ProcedureReturn GetGadgetText (*this \ Gadget)
EndProcedure
Procedure SetText (Gadget, Text$)
SetGadgetText (Gadget, Text$)
EndProcedure
Procedure ISetText (*this. SGadget, Text$)
SetGadgetText (*this \ Gadget, Text$)
EndProcedure
Procedure String (Gadget, x, y, Width, Height, Content$, Flags = #Null)
ProcedureReturn StringGadget (Gadget, x, y, Width, Height, Content$, Flags)
EndProcedure
Procedure NewString (Gadget, x, y, Width, Height, Content$, Flags = #Null)
Protected *this. SGadget
*this = AllocateStructure (SGadget)
If *this
*this \ VTABLE = ? VTABLE_SGadget
*this \ Gadget = StringGadget (Gadget, x, y, Width, Height, Content$, Flags)
ProcedureReturn *this
EndIf
EndProcedure
Procedure Text (Gadget, x, y, Width, Height, Text$, Flags = #Null)
ProcedureReturn TextGadget (Gadget, x, y, Width, Height, Text$, Flags)
EndProcedure
Procedure NewText (Gadget, x, y, Width, Height, Text$, Flags = #Null)
Protected *this. SGadget
*this = AllocateStructure (SGadget)
If *this
*this \ VTABLE = ? VTABLE_SGadget
*this \ Gadget = TextGadget (Gadget, x, y, Width, Height, Text$, Flags)
ProcedureReturn *this
EndIf
EndProcedure
DataSection
VTABLE_SGadget:
Data. i @ IDelete ()
Data. i @ IGadget ()
Data. i @ IGetText ()
Data. i @ ISetText ()
EndDataSection
EndModule
Code: Alles auswählen
;
; Str.pbi
Interface Str
Delete ()
Left. s (Length)
Len ()
RSet. s (Length, Character$ = " ")
Set (String$)
String. s ()
Field. s (Index, Delimiter$)
Trim. s (Character$ = " ")
EndInterface
DeclareModule Str
Declare$ Str__Left (String$, Length)
Declare Str__Len (String$)
Declare New (String$ = #Empty$)
Declare$ Str__RSet (String$, Length, Character$ = " ")
Declare$ Str__Str (Value.q)
Declare$ Field (String$, Index, Delimiter$)
Declare$ Str__Trim (String$, Character$ = " ")
EndDeclareModule
Module Str
Structure SString
*VTABLE
String$
EndStructure
Procedure IDelete (*this. SString)
FreeMemory (*this)
EndProcedure
Procedure$ Str__Left (String$, Length)
ProcedureReturn Left (String$, Length)
EndProcedure
Procedure$ ILeft (*this. SString, Length)
ProcedureReturn Left (*this \ String$, Length)
EndProcedure
Procedure Str__Len (String$)
ProcedureReturn Len (String$)
EndProcedure
Procedure ILen (*this. SString)
ProcedureReturn Len (*this \ String$)
EndProcedure
Procedure New (String$ = #Empty$)
Protected *this. SString
*this = AllocateMemory (SizeOf (SString))
If *this
*this \ VTABLE = ? VTABLE_SSTRING
*this \ String$ = String$
ProcedureReturn *this
EndIf
EndProcedure
Procedure$ Str__RSet (String$, Length, Character$ = " ")
ProcedureReturn RSet (String$, Length, Character$)
EndProcedure
Procedure$ IRSet (*this. SString, Length, Character$ = " ")
ProcedureReturn RSet (*this \ String$, Length, Character$)
EndProcedure
Procedure ISet (*this. SString, String$)
*this \ String$ = String$
EndProcedure
Procedure$ Str__Str (Value.q)
ProcedureReturn Str (Value.q)
EndProcedure
Procedure$ IString (*this. SString)
ProcedureReturn *this \ String$
EndProcedure
Procedure$ Field (String$, Index, Delimiter$)
ProcedureReturn StringField (String$, Index, Delimiter$)
EndProcedure
Procedure$ IField (*this. SString, Index, Delimiter$)
ProcedureReturn StringField (*this \ String$, Index, Delimiter$)
EndProcedure
Procedure$ Str__Trim (String$, Character$ = " ")
ProcedureReturn Trim (String$, Character$)
EndProcedure
Procedure$ ITrim (*this. SString, Character$ = " ")
ProcedureReturn Trim (*this \ String$, Character$)
EndProcedure
DataSection
VTABLE_SString:
Data. i @ IDelete ()
Data. i @ ILeft ()
Data. i @ ILen ()
Data. i @ IRSet ()
Data. i @ ISet ()
Data. i @ IString ()
Data. i @ IField ()
Data. i @ ITrim ()
EndDataSection
EndModule
Code: Alles auswählen
;
; Stringer.pb
IncludeFile "Window.pbi"
IncludeFile "Gadget.pbi"
IncludeFile "Str.pbi"
; Global StringInput, StringLen, StringLeft, StringField, StringTrim, StringRSet, TextInput, TextOutput
; Global Stringer
; Global DefaultString$
Global. Gadget StringInput, StringLen, StringLeft, StringField, StringTrim, StringRSet, TextInput, TextOutput
Global. Window Stringer
Global. Str String
; String$ = " Hallo, Welt, ! "
String = Str::New (" Hallo, Welt, ! ")
; Stringer = OpenWindow (#PB_Any, #PB_Ignore, #PB_Ignore, 460, 200, "Stringer", #PB_Window_SystemMenu| #PB_Window_ScreenCentered| #PB_Window_MinimizeGadget)
Stringer = Window::New (#PB_Any, #PB_Ignore, #PB_Ignore, 460, 200, "Stringer", #PB_Window_SystemMenu| #PB_Window_ScreenCentered| #PB_Window_MinimizeGadget)
; TextInput = TextGadget (#PB_Any, 20, 20, 100, 20, "Eingaben:")
TextInput = Gadget::NewText (#PB_Any, 20, 20, 100, 20, "Eingabe:")
; TextOutput = TextGadget (#PB_Any, 20, 90, 100, 20, "Ausgaben:")
TextOutput = Gadget::NewText (#PB_Any, 20, 90, 100, 20, "Ausgaben:")
; StringInput = StringGadget (#PB_Any, 20, 50, 200, 20, String$)
StringInput = Gadget::NewString (#PB_Any, 20, 50, 200, 20, String \ String ())
; StringLen = StringGadget (#PB_Any, 240, 90, 200, 20, "")
StringLen = Gadget::NewString (#PB_Any, 240, 90, 200, 20, "")
; StringLeft = StringGadget (#PB_Any, 20, 120, 200, 20, "")
StringLeft = Gadget::NewString (#PB_Any, 20, 120, 200, 20, "")
; StringField = StringGadget (#PB_Any, 240, 120, 200, 20, "")
StringField = Gadget::NewString (#PB_Any, 240, 120, 200, 20, "")
; StringTrim = StringGadget (#PB_Any, 20, 150, 200, 20, "")
StringTrim = Gadget::NewString (#PB_Any, 20, 150, 200, 20, "")
; StringRSet = StringGadget (#PB_Any, 240, 150, 200, 20, "")
StringRSet = Gadget::NewString (#PB_Any, 240, 150, 200, 20, "")
Procedure SetOutputGadgets ()
; String$ = GetGadgetText (StringInput)
String \ Set (StringInput \ GetText ())
; SetGadgetText (StringLen, Str (Len (String$)))
StringLen \ SetText (Str::Str__Str (String \ Len ()))
; SetGadgetText (StringLeft, Left (String$, 7))
StringLeft \ SetText (String \ Left (7))
; SetGadgetText (StringField, StringField (String$, 2, ", "))
StringField \ SetText (String \ Field (2, ", "))
; SetGadgetText (StringTrim, Trim (String$))
StringTrim \ SetText (String \ Trim ())
; SetGadgetText (StringRSet, RSet (String$, 20, "#"))
StringRSet \ SetText (String \ RSet (20, "#"))
EndProcedure
SetOutputGadgets ()
Repeat
; Select WaitWindowEvent ()
Select Window::WaitEvent ()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
; If EventGadget () = StringInput
If Window::Event__Gadget () = StringInput \ Gadget ()
SetOutputGadgets ()
EndIf
EndSelect
ForEver
End
Stringer.zip
[Extern] Ausführliche Bibliotheken (ungetestet und im Fall von Gadget.pbi unfertig):
Window.pbi
Gadget.pbi
Str.pbi
In der Version der String-Bibliothek (Str.pbi) wird die Zeichenkette zum Objekt. Viele Funktionen können dann direkt auf das Str-Objekt angewandt werden.
Jede PB-library bietet andere Möglichkeiten, aus Bibliotheken Objekte zu machen. Manche, wie die Requester-Bibliothek, brauchen gar kein Objekt - bieten aber Angriffsfläche für untergeordnete Klassen. So macht es keinen Sinn, eine Requester-Klasse zu bauen, da jeder Requester eine andere Funktionalität hat aber man könnte etwa eine Klasse für den OpenFileRequester bauen, die etwa bei Mehrfachauswahl das Abfragen der Dateinamen erleichtert.
Ich bitte um Meinungen, Anregungen und eventuell auch um Hilfe beim Erstellen, Fertigstellen und Testen der Includes. Teilweise funktioniert dies automatisiert mit Software, die ich verfasst habe. Manuelle Nachbesserung ist aber von Nöten. (Für eine größere Bibliothek braucht man etwa 1-1,5 Stunden.) Von Vorteil ist dabei, wenn man die Bibliothek kennt und genau weiß, wie sie funktioniert.