July 14, 2005
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
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


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
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
"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
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
"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
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
"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
> 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