Seite 2 von 3

Verfasst: 22.04.2005 16:16
von orange-blue
Interaces sind keine Klassen.

Verfasst: 22.04.2005 16:16
von Kukulkan
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

Verfasst: 22.04.2005 17:00
von johnlein
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.

Verfasst: 22.04.2005 17:36
von Mike0484
da wir hier schon bei den anfängern sind stelle ich doch gleich mal eine solche frage:
was ist der unterschied zwichen einer objektorientieten sprache und einer prozeduralen ?

Verfasst: 22.04.2005 18:04
von johnlein
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.

Verfasst: 22.04.2005 18:17
von Zaphod
oder um es für jemanden zu formulieren, der noch nicht objektorientiert programiert hat, der hauptunterschied ist der grad der modularität, die art des programmablaufes und der umgang mit daten.

das ideale objektorientierte programm würde nur aus objekten bestehen die untereinander kummunizieren.

Beleidigung

Verfasst: 22.04.2005 22:57
von Green Snake
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.....
sollte das eine beleidugung sein?

:mrgreen: :D :allright:

nein, war ein scherz... habe durch diese antwort nur meine meinung gesagt

Verfasst: 23.04.2005 19:32
von DarkDragon
orange-blue hat geschrieben:Interaces sind keine Klassen.
Ich sprech ja auch von Interfaces :mrgreen: :lol: . Nein im ernst: warum sagt das dann jeder und warum kann man sie so nutzen?

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

Verfasst: 23.04.2005 19:53
von Danilo
w0w, Dein Beispiel ist ja genauso aufgebaut wie meine... :D

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
Hier erbt Klasse 2 von Klasse 1:

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
Früher musste man immer schreiben:

Code: Alles auswählen

*win2.cWINDOW = WINDOW()
If *win2
   *win2\Open(0,0,400,300,"Name",#PB_Window_SystemMenu)
   *win2\Move(300,300)
EndIf
...also mit Pointern.

Siehe PB-Referenz zu Interfaces. Beides geht. Eines ist richtig.
Vielleicht auch beides. :D


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

Verfasst: 23.04.2005 20:24
von orange-blue
>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.