View mode: basic / threaded / horizontal-split · Log in · Help
July 14, 2005
Private and Protected Inheritance.
Hi there,

I've looked through the archives for info on this but didn't find much. I also
searched the docs, also in vain. My question is whether D supports, will
support, or will never support private and/or protected inheritance. Drawing an
analogy to C++, currently what D does is:

class Foo {}
class Bar : Foo {}
// is technically:
class Bar : public Foo {}
// in other words, public inheritance.

However, private and protected inheritance also exist. They can be very useful,
and would be a very welcome addition. I tried it w/ DMD 0.127, and though
curiously the syntax is legal, it doesn't alter the access level:

class Bar : private Foo {}   // compiles, but still public.
class Bar : protected Foo {} // compiles, but still public.

Note: I am aware about the possibility of casting up the object hierarchy to a
more open level (e.g. cast (Foo) someBar). Perhaps that could be made illegal.
Or not; it doesn't matter that much. The feature is useful regardless. Explicit
casts are always dangerous.

Thanks,
--AJG.
July 14, 2005
Re: Private and Protected Inheritance.
In article <db4sko$1qr6$1@digitaldaemon.com>, AJG says...
>
>However, private and protected inheritance also exist. They can be very useful,

Examples?

Private inheritance is normally used in C++ to achieve what D does far more
cleanly with mixins. As for protected, AFAIK there's no consensus in the C++
community on what it even _means_.
July 14, 2005
Re: Private and Protected Inheritance.
In article <db56ku$277j$1@digitaldaemon.com>, Mike Capp says...
>
>In article <db4sko$1qr6$1@digitaldaemon.com>, AJG says...
>>
>>However, private and protected inheritance also exist. They can be very useful,
>
>Examples?

Well, say you have a base class with a hefty and complex interface and/or
implementation (this doesn't mean badly-designed, though). E.g.:

class DeviceContext {
// ... uses threads ...
// ... and drivers ...
// ... and mutexes ...
// ... and various kernel objects ...
// ... and god knows what else ...
}

Then you want to create a higher-level object with a more abstract
representation. It should be safer too; without a way to screw the system up.
E.g.:

class Graphics : DeviceContext {
// Provides things like:
DrawCircle();
DrawSquare();
DrawTriangle();
// etc...
}

So, you can tell your users (or yourself) "use the Graphics class if you don't
want to see the gory hardware details." Yet with public inheritance, which is
the only option right now, a Graphics instance doesn't shield you against the
DeviceContext.

You can still mess things up at the lower level by calling inappropriate
functions and setting dangerous properties. Therefore, wouldn't it be nice to
have the requested inheritance facility?

Note: Yes, it _is_ possible to create a private instance of DeviceContext within
Graphics and then work from there. But this is sub-optimal because of various
reasons:

1) Graphics would not be able to extend DeviceContext.
2) Graphics has limited access to DeviceContext. All protected members are gone.
3) If DeviceContext was meant to be derived from, or is simply abstract, then
you need to create an intermediate class -hardly an elegant solution.

At any rate, I don't think this feature takes away anything from the language
and wouldn't conflict with any current code. In fact, a I said, I believe the
syntax is already valid. Could this be given some consideration?

Thanks,
--AJG.


>Private inheritance is normally used in C++ to achieve what D does far more
>cleanly with mixins. As for protected, AFAIK there's no consensus in the C++
>community on what it even _means_.

I don't think this should be too complicated. Members that would have been made
private (from public) are made protected instead.
July 14, 2005
Re: Private and Protected Inheritance.
In article <db61hd$2vek$1@digitaldaemon.com>, AJG says...
>
>Well, say you have a base class with a hefty and complex interface and/or
>implementation (this doesn't mean badly-designed, though). E.g.:
>
>[snip DeviceContext class]
>
>Then you want to create a higher-level object with a more abstract
>representation. It should be safer too; without a way to screw the system up.
>
>[snip Graphics class derived from DeviceContext]
>So, you can tell your users (or yourself) "use the Graphics class if you don't
>want to see the gory hardware details." Yet with public inheritance, which is
>the only option right now, a Graphics instance doesn't shield you against the
>DeviceContext.
>
>You can still mess things up at the lower level by calling inappropriate
>functions and setting dangerous properties. Therefore, wouldn't it be nice to
>have the requested inheritance facility?

But... but... isn't this exactly what interfaces are for? Define an IGraphics
interface with DrawCircle(), DrawSquare() etc, have your Graphics class
implement that interface, and give an IGraphics to client code instead of a
Graphics.

>>As for protected, AFAIK there's no consensus in the C++
>>community on what it even _means_.
>
>I don't think this should be too complicated. Members that would have been made
>private (from public) are made protected instead.

I meant "what it means semantically", rather than what the syntax looks like.
Public inheritance means "Derived is substitutable for Base". Private
inheritance means "Derived reuses code from base without exposing that fact in
its interface". What does protected inheritance mean?

cheers
Mike
July 14, 2005
Re: Private and Protected Inheritance.
"AJG" <AJG_member@pathlink.com> wrote in message 
news:db61hd$2vek$1@digitaldaemon.com...
> I don't think this should be too complicated. Members that would have been 
> made
> private (from public) are made protected instead.

Wouldn't that defeat the entire purpose of having the 'private' protection 
attribute?  It means "cannot be seen by ANYTHING, including derived 
classes."  If derived classes can override it, then it's no different than 
'protected.'
July 14, 2005
Re: Private and Protected Inheritance.
Hi,

>> I don't think this should be too complicated. Members that would have been 
>> made
>> private (from public) are made protected instead.
>
>Wouldn't that defeat the entire purpose of having the 'private' protection 
>attribute?  It means "cannot be seen by ANYTHING, including derived 
>classes."  If derived classes can override it, then it's no different than 
>'protected.' 

No, no, what I meant is this:

class Foo                 { public int A; }
class Bar : public    Foo { /* Derived A is still public.  */ }
class Bar : private   Foo { /* Derived A is now private.   */ }
class Bar : protected Foo { /* Derived A is now protected. */ }

In other words, the members that were originally (in the base class) public, but
would have been made private when using private inheritance, would be made
protected instead (when using protected inheritance).

Is that better?

Cheers,
--AJG.
July 14, 2005
Re: Private and Protected Inheritance.
"AJG" <AJG_member@pathlink.com> wrote in message 
news:db6qee$jmf$1@digitaldaemon.com...
> Is that better?

Much, thanks for the explanation.

However, private and protected inheritance seem like very "niche" and 
complex features for very little benefit.  In addition, it might not be 
possible to implement well in D, as a private function cannot be virtual - 
and changing a function's type from public to private when inherited 
wouldn't fly, given D's inbuilt "virtual" determination...
July 15, 2005
Re: Private and Protected Inheritance.
Jarrett Billingsley wrote:
> "AJG" <AJG_member@pathlink.com> wrote in message 
> news:db6qee$jmf$1@digitaldaemon.com...
> 
>>Is that better?
> 
> 
> Much, thanks for the explanation.
> 
> However, private and protected inheritance seem like very "niche" and 
> complex features for very little benefit.  In addition, it might not be 
> possible to implement well in D, as a private function cannot be virtual - 
> and changing a function's type from public to private when inherited 
> wouldn't fly, given D's inbuilt "virtual" determination... 
> 
> 

I don't know how hard would it be to implement, but I think there is a 
better way around it:

class A { /* stuff */ }

class B { private A a; /* other stuff */ }

I think that makes more sense, because if you want to hide A's interface 
then B probably is not an A, it just uses it.

Even the DeviceContext example, Graphics probably _uses_ a device 
context to draw stuff, but it's not really a device context.
Ofcourse I'm just making assumptions here, but my feeling is if you need 
to hide the super classes interface then you probably are not of the 
same type as the super class.
July 15, 2005
Re: Private and Protected Inheritance.
"AJG" <AJG_member@pathlink.com> wrote in message 
news:db61hd$2vek$1@digitaldaemon.com...
>
>
>
> In article <db56ku$277j$1@digitaldaemon.com>, Mike Capp says...
>>
>>In article <db4sko$1qr6$1@digitaldaemon.com>, AJG says...
>>>
>>>However, private and protected inheritance also exist. They can be very 
>>>useful,
>>
>>Examples?
>
> Well, say you have a base class with a hefty and complex interface and/or
> implementation (this doesn't mean badly-designed, though). E.g.:
>
> class DeviceContext {
> // ... uses threads ...
> // ... and drivers ...
> // ... and mutexes ...
> // ... and various kernel objects ...
> // ... and god knows what else ...
> }
>
> Then you want to create a higher-level object with a more abstract
> representation. It should be safer too; without a way to screw the system 
> up.
> E.g.:
>
> class Graphics : DeviceContext {
> // Provides things like:
> DrawCircle();
> DrawSquare();
> DrawTriangle();
> // etc...
> }

Try this:

From Harmonia:
---------------------------------------------------
module harmonia.ui.native.win32graphics;

class NativeGraphics
{
  package
  {
     // ... various native objects ...
     void nativeDrawRect(rect rc) { .... }
  }
}
---------------------------------------------------
module harmonia.gx.graphics;

class Graphics: NativeGraphics
{
   void drawRect(rect rc)
   {
     nativeDrawRect(rc);
   }
}

--------------------------

void testDraw(Graphics g)
 {
   g.nativeDrawRect(place);
//  Error: class harmonia.gx.graphics.Graphics
//  member nativeDrawRect is not accessible
 }

---------------------------
July 15, 2005
Re: Private and Protected Inheritance.
> Ofcourse I'm just making assumptions here, but my feeling is if you need  
> to hide the super classes interface then you probably are not of the  
> same type as the super class.

Exactly.

Ciao
uwe
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home