Module Inheritance (or Acces Module from other Module)

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
grabiller
Enthusiast
Enthusiast
Posts: 309
Joined: Wed Jun 01, 2011 9:38 am
Location: France - 89220 Rogny-Les-Septs-Ecluses
Contact:

Module Inheritance (or Acces Module from other Module)

Post by grabiller »

Hello,

While experimenting with the new Module feature, which I quite like, I've stumble upon an issue that defeats the Module main purpose which is, from my understanding, encapsulation.

This, in the context of 'Classes' creation (with Interface/Structure/DataSection/..).

Lets say I have this 'Class' in a module:

Code: Select all

DeclareModule CObject
  Interface Instance
    RefInc.i ()
    RefDec.i ()
  EndInterface
EndDeclareModule
Module CObject
  Structure Instance_t
    *vtable
    rfc.l
  EndStructure
EndModule
I don't show the code for implementing constructors nor the two 'Class methods' (RefInc & RefDec) as the point here is inheritance.

Now let say I want to create another 'Class' which inherits from the CObject 'Class'.

Code: Select all

DeclareModule CDerived
  Interface Instance Extends CObject::Instance
    Plop.i ()
  EndInterface
  Declare.i New()
EndDeclareModule
Module CDerived
  Structure Instance_t Extends CObject::Instance_t
    myplop.i
  EndStructure
  Procedure.i New()
  EndProcedure
EndModule

; The intended use:
Define *d.CDerived::Instance = CDerived::New()
For the Interface, everything works as expected, but not for the 'Instance' structure, as the CObject::Instance_t structure is declared in the CObject 'Module' not in the CObject 'DeclareModule' section.

The Module section is considered as a 'private' section where data cannot be seen outside of this Module section.

The drawback of this is that for inheritance to work, we have to declare the CObject::Instance_t structure into the CObject 'DeclareModule' instead of the CObject 'Module' section. But doing this, the CObject::Instance_t becomes public and everyone can access it, which defeat the encapsulation concept brought by the Module feature.

To solve this issue I'm thinking about allowing code inside private Module sections to access any other private Module sections data.

It wouldn't be 100% encapsulation of course, but at least code inside private 'Module' sections would be seen only from other private 'Module' sections, not from main code or anywhere else.

Or perhaps there is another way ?

Cheers,
Guy.
guy rabiller | radfac founder / ceo | raafal.org
Justin
Addict
Addict
Posts: 948
Joined: Sat Apr 26, 2003 2:49 pm

Re: Module Inheritance (or Acces Module from other Module)

Post by Justin »

It has been requested
http://www.purebasic.fr/english/viewtop ... =3&t=55122
And here some talk about inheritance, some think is evil
http://www.purebasic.fr/english/viewtop ... 12&t=55630
User avatar
grabiller
Enthusiast
Enthusiast
Posts: 309
Joined: Wed Jun 01, 2011 9:38 am
Location: France - 89220 Rogny-Les-Septs-Ecluses
Contact:

Re: Module Inheritance (or Acces Module from other Module)

Post by grabiller »

Justin wrote:It has been requested
http://www.purebasic.fr/english/viewtop ... =3&t=55122
And here some talk about inheritance, some think is evil
http://www.purebasic.fr/english/viewtop ... 12&t=55630
Thanks Justin for pointing it.

Regarding inheritance: single inheritance is good, multiple inheritance is evil. :wink:

Cheers,
Guy.
guy rabiller | radfac founder / ceo | raafal.org
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: Module Inheritance (or Acces Module from other Module)

Post by Danilo »

grabiller wrote:Or perhaps there is another way ?
You could use a global object module (I don't recommend it for your use):

Code: Select all

DeclareModule ObjectSystemGlobals
    Structure CObject_t
        *vtable
        rfc.l
    EndStructure
    
    Structure CDerived_t Extends CObject_t
        myplop.i
    EndStructure
    
EndDeclareModule

Module ObjectSystemGlobals
EndModule


DeclareModule CObject
    
    Interface Instance
        RefInc.i()
        RefDec.i()
    EndInterface
    
EndDeclareModule

Module CObject
EndModule


DeclareModule CDerived
    
    Interface Instance Extends CObject::Instance
        Plop.i()
    EndInterface
    
    Declare.i New()
    
EndDeclareModule

Module CDerived
    
    ;UseModule ObjectSystemGlobals
    
    Procedure.i New()
        Debug SizeOf(CObject::Instance)
        Debug SizeOf(CDerived::Instance)
        
        
        Debug SizeOf(ObjectSystemGlobals::CObject_t)
        Debug SizeOf(ObjectSystemGlobals::CDerived_t)
        
        ;Debug SizeOf(CObject_t)
        ;Debug SizeOf(CDerived_t)
        
    EndProcedure
    
EndModule



; The intended use:
Define *d.CDerived::Instance = CDerived::New()

I think it would be better for you to create extra modules. They start with '_' in this example and are for internal use only:

Code: Select all

;
;- CObject
;
DeclareModule _CObject
    
    Structure Instance_t
        *vtable
        rfc.l
        var1.i
        var2.i
    EndStructure
    
EndDeclareModule

Module _CObject
EndModule


DeclareModule CObject
    
    Interface Instance
        RefInc.i()
        RefDec.i()
    EndInterface
    
EndDeclareModule

Module CObject
    UseModule _CObject ; import CObject globals
EndModule



;
;- CDerived
;
DeclareModule _CDerived
    
    Structure Instance_t Extends _CObject::Instance_t
        myplop.i
        var3.i
    EndStructure
    
EndDeclareModule

Module _CDerived
EndModule


DeclareModule CDerived
    
    Interface Instance Extends CObject::Instance
        Plop.i()
    EndInterface
    
    Declare.i New()
    
EndDeclareModule

Module CDerived

    UseModule _CDerived ; import CDerived globals

    Procedure.i New()
        
        Debug SizeOf(CObject::Instance)
        Debug SizeOf(CDerived::Instance)
        
        
        Debug SizeOf(_CObject::Instance_t)
        Debug SizeOf(_CDerived::Instance_t)
        
    EndProcedure
    
EndModule

;
;- Program
;

; The intended use:
Define *d.CDerived::Instance = CDerived::New()
Best we can do for now... ;)
Post Reply