OOP Without interfaces

Share your advanced PureBasic knowledge/code with the community.
Hydrate
Enthusiast
Enthusiast
Posts: 436
Joined: Mon May 16, 2005 9:37 pm
Contact:

OOP Without interfaces

Post by Hydrate »

This is just a really basic example I got bored and made when I got home from work today. It demonstrates the creation of a class, inheritance of that class and the creation of objects, all without using interfaces, or anything overly complicated to new users of Purebasic. I have no idea how useful it will be to anyone, but better to post it than for it to go entirely to waste.

Enjoy:

Code: Select all

; Simple Purebasic OOP example

; Format for classes:
;   PROTOTYPES      - Only necessary for methods not in parent classes. Declared first so that the structure can read it.
;   STRUCTURE       - Variables, then methods, order doesnt really matter. - METHODNAME.PROTOTYPE
;   METHODS         - Methods with 'CLASSNAME_' before them to distinguish between them and procedures
;   CONSTRUCTOR     - At the bottom so it can set all of the methods appropriately
; 

;{ Class Rectangle
Prototype Rectangle_size(*this, width.i, height.i);
Prototype Rectangle_move(*this, x.i, y.i);
  
  Structure Rectangle;
    x.i;
    y.i;
    width.i;
    height.i;
    
    size.Rectangle_size;
    move.Rectangle_move;
  EndStructure;
  
  Procedure Rectangle_size(*this.Rectangle, width.i, height.i);
    *this\width = width;
    *this\height = height;
  EndProcedure;
  
  
  Procedure Rectangle_move(*this, x.i, y.i)
    Debug "moving";
  EndProcedure;
  
  ; Constructor
  Procedure Rectangle_(*this.Rectangle);
    *this\size = @Rectangle_size();
    *this\move = @Rectangle_move();
  EndProcedure;
;}



;{ Class ColouredRectangle
  Structure ColouredRectangle Extends Rectangle;
    colour.l;
  EndStructure;
  
  ; Method override for size
  Procedure ColouredRectangle_size(*this.ColouredRectangle, width.i, height.i);
    *this\width = width;
    *this\height = height;
    Debug "Coloured sizing instead!";
  EndProcedure;
  
  ; Constructor
  Procedure ColouredRectangle_(*this.ColouredRectangle);
    Rectangle_(*this);
    
    *this\size = @ColouredRectangle_size();
  EndProcedure;
;}



; Rectangle myRect = new Rectangle()
Rectangle_(myRect.Rectangle);
myRect\size(myRect, 20,20);
Debug myRect\width;



; ColouredRectangle mycRect = new ColouredRectangle()
ColouredRectangle_(mycRect.ColouredRectangle);
mycRect\colour = RGB(20,12,20);
mycRect\size(mycRect,22,91);
Debug mycRect\colour;
.::Image::.
User avatar
Demivec
Addict
Addict
Posts: 4086
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: OOP Without interfaces

Post by Demivec »

Thanks for the example.
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: OOP Without interfaces

Post by skywalk »

Seems rather compact and easy to follow.
Is there any need to free memory or a Destructor?
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Re: OOP Without interfaces

Post by rsts »

Nice :)

Thanks for sharing.
Hydrate
Enthusiast
Enthusiast
Posts: 436
Joined: Mon May 16, 2005 9:37 pm
Contact:

Re: OOP Without interfaces

Post by Hydrate »

skywalk wrote:Seems rather compact and easy to follow.
Is there any need to free memory or a Destructor?
Because it uses none of the complex features in Purebasic (simply uses a struct), you can destruct an object simply by using the ClearStructure() command.

It also means that copying an object is very easy. You can do it with:

Code: Select all

myRect2.Rectangle = myRect.Rectangle
Debug myRect2\width;
.::Image::.
User avatar
STARGÅTE
Addict
Addict
Posts: 2067
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: OOP Without interfaces

Post by STARGÅTE »

without interfaces, you must give the own object to the procedure.
mycRect\size(mycRect, 22, 91);
if that is not complicated, it is ok.
But an interface would not need it:
mycRect\size(22, 91);
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
inc.
Enthusiast
Enthusiast
Posts: 406
Joined: Thu May 06, 2004 4:28 pm
Location: Cologne/GER

Re: OOP Without interfaces

Post by inc. »

mycRect\size(mycRect, 22, 91);
And beside this .... its almost the way of handling objects like PB does it already
RectSize(#myRectNum, 22, 91)
So approaches where you have to provide the object pointer to methods are object based, but not object orientated.

Theres a way on 32bit compiles, but seems to be unsafe .... and maybe not supported by future PB versions:

Code: Select all

Declare.l Test_get()
Declare.s Test_set(val.l)
Prototype.l Test_get()
Prototype.s Test_set(val.l)

Structure Test
	get.Test_get
	set.Test_set
	Handle.l
EndStructure

Procedure.l Test_get()
	Protected *this.Test
	!MOV [p.p_this],Ebp
	ProcedureReturn *this\Handle
EndProcedure

Procedure.s Test_set(val.l)
	Protected *this.Test
	!MOV [p.p_this],Ebp
	*this\Handle = val
	ProcedureReturn "bla"
EndProcedure

Procedure _createTest(Size.l)
	If Size<SizeOf(Test)
	Size = SizeOf(Test)
	EndIf
	Protected *this.Test = AllocateMemory(SizeOf(Test))
	*this\get=@Test_get()
	*this\set=@Test_set()
	*this\Handle = 666
	ProcedureReturn *this
EndProcedure

Procedure.l Test()
	ProcedureReturn _createTest(0)
EndProcedure

*b.Test = Test()
Debug *b\get()
Debug *b\set(9999999)
Debug *b\Handle
Check out OOP support for PB here!
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: OOP Without interfaces

Post by ts-soft »

inc. wrote:Theres a way on 32bit compiles, but seems to be unsafe .... and maybe not supported by future PB versions:

Code: Select all

Declare.l Test_get()
Declare.s Test_set(val.l)
Prototype.l Test_get()
Prototype.s Test_set(val.l)

Structure Test
   get.Test_get
   set.Test_set
   Handle.l
EndStructure

Procedure.l Test_get()
   Protected *this.Test
   CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
   !MOV [p.p_this],Rbp
   CompilerElse
   !MOV [p.p_this],Ebp
   CompilerEndIf
   ProcedureReturn *this\Handle
EndProcedure

Procedure.s Test_set(val.l)
   Protected *this.Test
   CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
   !MOV [p.p_this],Rbp
   CompilerElse
   !MOV [p.p_this],Ebp
   CompilerEndIf
   *this\Handle = val
   ProcedureReturn "bla"
EndProcedure

Procedure _createTest(Size.l)
   If Size<SizeOf(Test)
   Size = SizeOf(Test)
   EndIf
   Protected *this.Test = AllocateMemory(SizeOf(Test))
   *this\get=@Test_get()
   *this\set=@Test_set()
   *this\Handle = 666
   ProcedureReturn *this
EndProcedure

Procedure.l Test()
   ProcedureReturn _createTest(0)
EndProcedure

*b.Test = Test()
Debug *b\get()
Debug *b\set(9999999)
Debug *b\Handle 
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
inc.
Enthusiast
Enthusiast
Posts: 406
Joined: Thu May 06, 2004 4:28 pm
Location: Cologne/GER

Re: OOP Without interfaces

Post by inc. »

Nice :-)
Check out OOP support for PB here!
User avatar
chikega
User
User
Posts: 34
Joined: Fri Dec 04, 2020 3:19 am

Re: OOP Without interfaces

Post by chikega »

10 years later .. still a nice example that I can learn from. Thank you. :D
Gary E Chike DMD MS
'Experience is what you get when you don't get what you want' Image
Post Reply