OO in PureBasic
-
- Beiträge: 556
- Registriert: 04.09.2004 22:23
- Kontaktdaten:
Hallo johnlein,
Tatsächlich hat Didelphodon einen PreCompiler entwickelt der normalen OOP-Code in einen PB-kompatiblen Code übersetzt. Soweit ich das sehe funktioniert das schon recht gut (mit kleinen Einschränkungen).
Mehr dazu findest Du unter dem PBE-Projekt:
http://members.chello.at/pure-basic-essentials/
Also los! Ran an die Klassen, Methoden und Extends...
Grüsse,
Volker
Tatsächlich hat Didelphodon einen PreCompiler entwickelt der normalen OOP-Code in einen PB-kompatiblen Code übersetzt. Soweit ich das sehe funktioniert das schon recht gut (mit kleinen Einschränkungen).
Mehr dazu findest Du unter dem PBE-Projekt:
http://members.chello.at/pure-basic-essentials/
Also los! Ran an die Klassen, Methoden und Extends...
Grüsse,
Volker
Danke für die ganze Information, und den link zum preprozessor. Ich hab auch nen link zu dem thread unter allgemeines gefunden. Ich schaus mir jetzt mall genauer an.
Zu der Sache das OO nicht nötig ist, sag ich nur das richtige tool für den richtigen job. Manchmal sind das Funktionen manchmal sind das klassen, aber das ist nur meine Meinung.
Danke nochmals.
Zu der Sache das OO nicht nötig ist, sag ich nur das richtige tool für den richtigen job. Manchmal sind das Funktionen manchmal sind das klassen, aber das ist nur meine Meinung.
Danke nochmals.
Naja, die meisten Objekt Orientierten sprachen sind auch Prozedurale Sprachen, da sie aus ihnen gewachsen sind. In einer Prozeduralen Sprache (auch Imperative Sprache genant und da gibt’s noch mehr Namen aber das tut ja nichts zur Sache) hast du Prozeduren/Funktionen, das sind Selbstständige Code abschnitte die vom Haupt Programm aus gerufen werden können. Wen du Kapselung hinzufügst hast du Modulares programmieren, wen du dazu Objekte/klassen hinzufügst hast du Objekt Orientiertes programmieren. Eine Klasse ist eine Sammlung von Daten Typen gekoppelt mit einer Sammlung von Methoden (dasselbe eigentlich wie Funktionen mit dem unterscheid das sie nur in klassen vorkommen, daher der andere Name). Kapselung wirkt sich auf die Klasse so aus das nur die Daten Typen und Methoden von außerhalb der klasse gesehen werden können die du gesehen haben willst. Ein Objekt ist eine Instanz einer Klasse, Objekte verhalten sich also zu Klassen wie Typen zu Variablen. Die Ausnahme bilden statische Klassen die direkt gerufen werden aber die werden nicht von allen Objekt Orientierten sprachen unterstütz.
Ich kann noch Ausführlicher werden falls das nicht hilft.
Ich kann noch Ausführlicher werden falls das nicht hilft.
- Green Snake
- Beiträge: 1394
- Registriert: 22.02.2005 19:08
Beleidigung
sollte das eine beleidugung sein?NicTheQuick hat geschrieben:@johnlein: Anstatt hier Erfahrungen von Anfängern zu sammeln, die in diesem Fall wenig aussagekräftig sind und kaum der Wahrheit entsprechen.....



nein, war ein scherz... habe durch diese antwort nur meine meinung gesagt
-.-"
-
- Beiträge: 6291
- Registriert: 29.08.2004 08:37
- Computerausstattung: Hoffentlich bald keine mehr
- Kontaktdaten:
Ich sprech ja auch von Interfacesorange-blue hat geschrieben:Interaces sind keine Klassen.


Bsp:
Code: Alles auswählen
Interface cEditorGadget
Create.l(x, y, width, height)
SetText.l(String.s)
Remove.l()
EndInterface
Structure cEditorGadget_OBJ
VTable.l
ID.l
Functions.l[SizeOf(cEditorGadget)/4]
EndStructure
Procedure.l cEditorGadget_Create(*this.cEditorGadget_OBJ, x, y, width, height)
*this\ID = EditorGadget(#PB_Any, x, y, width, height)
ProcedureReturn *this\ID
EndProcedure
Procedure.l cEditorGadget_SetText(*this.cEditorGadget_OBJ, String.s)
ProcedureReturn SetGadgetText(*this\ID, String.s)
EndProcedure
Procedure.l cEditorGadget_Remove(*this.cEditorGadget_OBJ)
ProcedureReturn FreeGadget(*this\ID)
EndProcedure
Procedure cEditorGadget()
*object.cEditorGadget_OBJ = AllocateMemory(SizeOf(cEditorGadget_OBJ))
If *object=0: ProcedureReturn 0: EndIf ; memory allocation failed
*object\VTable = *object+OffsetOf(cEditorGadget_OBJ\Functions)
*object\Functions[0] = @cEditorGadget_Create ()
*object\Functions[1] = @cEditorGadget_SetText()
*object\Functions[2] = @cEditorGadget_Remove ()
ProcedureReturn *object
EndProcedure
Procedure Destruct_cEditorGadget(*object.cEditorGadget)
FreeMemory(*object)
EndProcedure
#WindowWidth = 640
#WindowHeight = 480
#WindowFlags = #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_SystemMenu
hWnd = OpenWindow(0, 0, 0, #WindowWidth, #WindowHeight, #WindowFlags, "")
CreateGadgetList(WindowID())
*obj1.cEditorGadget = cEditorGadget()
If *obj1
*obj1\Create(0, 0, 640, 480)
*obj1\SetText("Hello World !")
EndIf
Repeat
Event = WindowEvent()
Delay(10)
Until Event = #PB_Event_CloseWindow
Destruct_cEditorGadget(*obj1)
End
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
w0w, Dein Beispiel ist ja genauso aufgebaut wie meine... 
Hier erbt Klasse 2 von Klasse 1:
Laut PB-Referenz ist es jetzt so richtig:
Früher musste man immer schreiben:
...also mit Pointern.
Siehe PB-Referenz zu Interfaces. Beides geht. Eines ist richtig.
Vielleicht auch beides.
PS: Wenn man sowas sieht ist man gleich froh das es C++ gibt - ist ja echt ein Krampf so.

Code: Alles auswählen
#HEAP_ZERO_MEMORY = $00000008
Procedure GetHeap()
!MOV dword EAX ,[PB_MemoryBase]
!MOV dword [ESP], EAX
ProcedureReturn Heap
EndProcedure
Structure DEFAULT_OBJ
VTable.l
ObjData.l
EndStructure
Procedure GetDataPointer(*obj.DEFAULT_OBJ)
ProcedureReturn *obj\ObjData
EndProcedure
;- CLASS cWINDOW start
; cWINDOW CLASS Interface
Interface cWINDOW
Open(x,y,w,h,name$,flags)
Move(x,y)
EndInterface
; cWINDOW CLASS Data Struct
Structure sWINDOW
hWnd.l
hPB.l
EndStructure
; cWINDOW CLASS Object
Structure cWINDOW_OBJ Extends DEFAULT_OBJ
Functions.l[SizeOf(cWINDOW)/4]
EndStructure
Procedure cWINDOW__Open(*this.cWINDOW,x,y,w,h,name$,flags)
*dp.sWINDOW = GetDataPointer(*this)
If *dp
*dp\hPB = OpenWindow(#PB_Any,x,y,w,h,flags,name$)
*dp\hWnd = WindowID(*dp\hPB)
ProcedureReturn *dp\hPB
EndIf
EndProcedure
Procedure cWINDOW__Move(*this.cWINDOW,x,y)
*dp.sWINDOW = GetDataPointer(*this)
If *dp
UseWindow(*dp\hPB)
MoveWindow(x,y)
EndIf
EndProcedure
; cWINDOW CLASS Constructor
Procedure cWINDOW__Constructor(ExtendFunction, ExtendData)
; Function table
*object.cWINDOW_OBJ = HeapAlloc_(GetHeap(),#HEAP_ZERO_MEMORY,ExtendFunction+SizeOf(cWINDOW_OBJ))
If *object=0: ProcedureReturn 0: EndIf
; Data
*ObjData.sWINDOW = HeapAlloc_(GetHeap(),#HEAP_ZERO_MEMORY,ExtendData+SizeOf(sWINDOW))
If *ObjData=0: HeapFree_(GetHeap(),0,*object) : ProcedureReturn 0: EndIf
*object\VTable = *object+OffsetOf(cWINDOW_OBJ\Functions)
*object\ObjData = *ObjData
*object\Functions[0] = @cWINDOW__Open()
*object\Functions[1] = @cWINDOW__Move()
ProcedureReturn *object
EndProcedure
; cWINDOW CLASS itself
Procedure WINDOW()
ProcedureReturn cWINDOW__Constructor(0,0)
EndProcedure
;- CLASS cWINDOW end
;- Program Start
; *win1.cWINDOW = WINDOW()
; If *win1
; *win1\Open(0,0,400,300,"Name",#PB_Window_SystemMenu)
; *win1\Move(300,300)
; EndIf
win2.cWINDOW = WINDOW()
If win2
win2\Open(0,0,400,300,"Name",#PB_Window_SystemMenu)
win2\Move(300,300)
EndIf
Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
Code: Alles auswählen
#HEAP_ZERO_MEMORY = $00000008
Procedure GetHeap()
!MOV dword EAX ,[PB_MemoryBase]
!MOV dword [ESP], EAX
ProcedureReturn Heap
EndProcedure
Structure DEFAULT_OBJ
VTable.l
ObjData.l
EndStructure
Procedure GetDataPointer(*obj.DEFAULT_OBJ)
ProcedureReturn *obj\ObjData
EndProcedure
;- CLASS cTEST start
; cTest CLASS Interface
Interface cTEST
Procedure1()
Procedure2(String$)
SetX(x)
SetY(y)
SetString(String$)
EndInterface
; cTest CLASS Data Struct
Structure sTEST
x.l
y.l
String$
EndStructure
; cTest CLASS Object
Structure cTEST_OBJ
VTable.l
ObjData.l
Functions.l[SizeOf(cTEST)/4]
EndStructure
Procedure cTEST__Procedure1(*this.cTEST)
MessageRequester("INFO","Procedure 1 in cTEST")
EndProcedure
Procedure cTEST__Procedure2(*this.cTEST, String$)
MessageRequester("INFO",String$)
EndProcedure
Procedure cTEST__SetX(*this.cTEST, x)
*this_data.sTEST = GetDataPointer(*this)
*this_data\x = x
EndProcedure
Procedure cTEST__SetY(*this.cTEST, y)
*this_data.sTEST = GetDataPointer(*this)
*this_data\y = y
EndProcedure
Procedure cTEST__SetString(*this.cTEST, String$)
*this_data.sTEST = GetDataPointer(*this)
*this_data\String$ = String$
EndProcedure
; cTEST CLASS Constructor
Procedure cTEST__Constructor(ExtendFunction, ExtendData)
; Function table
*object.cTEST_OBJ = HeapAlloc_(GetHeap(),#HEAP_ZERO_MEMORY,ExtendFunction+SizeOf(cTEST_OBJ))
If *object=0: ProcedureReturn 0: EndIf
; Data
*ObjData.sTEST = HeapAlloc_(GetHeap(),#HEAP_ZERO_MEMORY,ExtendData+SizeOf(sTEST))
If *ObjData=0: HeapFree_(GetHeap(),0,*object) : ProcedureReturn 0: EndIf
*object\VTable = *object+OffsetOf(cTEST_OBJ\Functions)
*object\ObjData = *ObjData
*object\Functions[0] = @cTEST__Procedure1()
*object\Functions[1] = @cTEST__Procedure2()
*object\Functions[2] = @cTEST__SetX()
*object\Functions[3] = @cTEST__SetY()
*object\Functions[4] = @cTEST__SetString()
ProcedureReturn *object
EndProcedure
; cTEST CLASS itself
Procedure cTEST()
ProcedureReturn cTEST__Constructor(0,0)
EndProcedure
;- CLASS cTEST end
;- CLASS cTest2 start
; cTest2 CLASS Interface
Interface cTEST2 Extends cTEST
SetZ(z)
GetX()
GetY()
GetZ()
GetString.s()
SetFloat(f.f)
GetFloat.f()
EndInterface
; cTest2 CLASS Data Struct
Structure sTEST2 Extends sTEST
z.l
float.f
EndStructure
; cTest2 CLASS Object
Structure cTEST2_OBJ ; Extends DEFAULT_OBJ
VTable.l
ObjData.l
Functions.l[SizeOf(cTEST)/4+SizeOf(cTEST2)/4]
EndStructure
Procedure cTEST2__SetZ(*this.cTEST2, z)
*this_data.sTEST2 = GetDataPointer(*this)
*this_data\z = z
EndProcedure
Procedure cTEST2__GetX(*this.cTEST2)
*this_data.sTEST2 = GetDataPointer(*this)
ProcedureReturn *this_data\x
EndProcedure
Procedure cTEST2__GetY(*this.cTEST2)
*this_data.sTEST2 = GetDataPointer(*this)
ProcedureReturn *this_data\y
EndProcedure
Procedure cTEST2__GetZ(*this.cTEST2)
*this_data.sTEST2 = GetDataPointer(*this)
ProcedureReturn *this_data\z
EndProcedure
Procedure.s cTEST2__GetString(*this.cTEST2)
*this_data.sTEST2 = GetDataPointer(*this)
ProcedureReturn *this_data\String$
EndProcedure
Procedure cTEST2__SetFloat(*this.cTEST2, f.f)
*this_data.sTEST2 = GetDataPointer(*this)
*this_data\float = f
EndProcedure
Procedure.f cTEST2__GetFloat(*this.cTEST2)
*this_data.sTEST2 = GetDataPointer(*this)
ProcedureReturn *this_data\float
EndProcedure
Procedure cTEST2__Procedure1(*this.cTEST)
MessageRequester("INFO","Procedure 1, but now in cTEST2")
EndProcedure
; cTEST2 Constructor
Procedure cTEST2__Constructor(ExtendFunction, ExtendData)
; Inherits from cTEST !!
*object.cTEST2_OBJ = cTEST__Constructor(ExtendFunction+(SizeOf(cTEST2)-SizeOf(cTEST)), ExtendData+SizeOf(sTEST2)-SizeOf(sTEST))
If *object=0: ProcedureReturn 0: EndIf
; overwrite old Function
*object\Functions[OffsetOf(cTEST\Procedure1())/4] = @cTEST2__Procedure1()
; add new functions to Table
#cTEST2__proc = SizeOf(cTEST)/4
*object\Functions[#cTEST2__proc+0] = @cTEST2__SetZ()
*object\Functions[#cTEST2__proc+1] = @cTEST2__GetX()
*object\Functions[#cTEST2__proc+2] = @cTEST2__GetY()
*object\Functions[#cTEST2__proc+3] = @cTEST2__GetZ()
*object\Functions[#cTEST2__proc+4] = @cTEST2__GetString()
*object\Functions[#cTEST2__proc+5] = @cTEST2__SetFloat()
*object\Functions[#cTEST2__proc+6] = @cTEST2__GetFloat()
ProcedureReturn *object
EndProcedure
; cTEST2 CLASS itself
Procedure cTEST2()
ProcedureReturn cTEST2__Constructor(0,0)
EndProcedure
;- cTEST2 CLASS end
;- Program Start
*obj1.cTEST = cTEST()
If *obj1
*obj1\Procedure1()
*obj1\Procedure2("Hello World !")
*obj1\SetX(12)
*obj1\SetY(15)
*obj1\SetString("Yo !")
EndIf
*obj2.cTEST2 = cTEST2()
If *obj2
*obj2\Procedure1()
*obj2\Procedure2("Hello World !")
*obj2\SetX(12)
*obj2\SetY(15)
*obj2\SetZ(18)
*obj2\SetString("Class 2")
*obj2\SetFloat(1.234567)
Debug *obj2\GetX()
Debug *obj2\GetY()
Debug *obj2\GetZ()
Debug *obj2\GetString()
Debug *obj2\GetFloat()
; direct data access
Debug "-- direct data access"
*data2.sTEST2 = GetDataPointer(*obj2)
*data2\x = 100
*data2\y = 200
*data2\z = 300
*data2\String$ = "New String"
*data2\float = 55.667788
Debug *obj2\GetX()
Debug *obj2\GetY()
Debug *obj2\GetZ()
Debug *obj2\GetString()
Debug *obj2\GetFloat()
EndIf
Laut PB-Referenz ist es jetzt so richtig:
Code: Alles auswählen
win2.cWINDOW = WINDOW()
If win2
win2\Open(0,0,400,300,"Name",#PB_Window_SystemMenu)
win2\Move(300,300)
EndIf
Code: Alles auswählen
*win2.cWINDOW = WINDOW()
If *win2
*win2\Open(0,0,400,300,"Name",#PB_Window_SystemMenu)
*win2\Move(300,300)
EndIf
Siehe PB-Referenz zu Interfaces. Beides geht. Eines ist richtig.
Vielleicht auch beides.

PS: Wenn man sowas sieht ist man gleich froh das es C++ gibt - ist ja echt ein Krampf so.

cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
-
- Beiträge: 556
- Registriert: 04.09.2004 22:23
- Kontaktdaten:
>warum sagt das dann jeder und warum kann man sie so nutzen?
Weil man sie in PB so nutzen kann(da es ja ne Prozedurale sprache is).
Interfaces haben keinen asuführbaren code sondern legt nur den Typ einer Klasse fest.
Aber ich persöhnlich finde Interfaces sowieso sinnlos(zumindest in Java).
In PB wären mir Klassen lieber, aber es auch nicht unbedingt sein.
Weil man sie in PB so nutzen kann(da es ja ne Prozedurale sprache is).
Interfaces haben keinen asuführbaren code sondern legt nur den Typ einer Klasse fest.
Aber ich persöhnlich finde Interfaces sowieso sinnlos(zumindest in Java).
In PB wären mir Klassen lieber, aber es auch nicht unbedingt sein.