Jump to page: 1 2 3
Thread overview
Frustrated by 'protected' again
Dec 18, 2005
Sean Kelly
Dec 19, 2005
Derek Parnell
Dec 19, 2005
Regan Heath
Dec 19, 2005
Manfred Nowak
Dec 19, 2005
Tom
Dec 20, 2005
Manfred Nowak
Dec 19, 2005
Derek Parnell
Dec 19, 2005
Hasan Aljudy
Dec 19, 2005
Ant
Dec 19, 2005
Chris Sauls
Dec 19, 2005
Ant
Dec 20, 2005
Chris Sauls
Dec 21, 2005
Mike Parker
Dec 20, 2005
Manfred Nowak
Specification Priority (was: Frustrated by 'protected' again)
Dec 20, 2005
Derek Parnell
Dec 21, 2005
Walter Bright
Re: Specification Priority
Dec 21, 2005
Bruno Medeiros
Dec 21, 2005
Derek Parnell
Dec 21, 2005
Manfred Nowak
Dec 22, 2005
Manfred Nowak
Dec 21, 2005
Manfred Nowak
December 18, 2005
I posted this a while ago, but the problem still has not been addressed. Mostly because Walter doesn't think it's a problem.

[file1.d]

class A
{
    protected int x;
}

[file2.d]

import file1;

class B : A
{
    void fork()
    {
        x = 5; // OK

        B b = new B;
        b. x = 8;  // OK

        A a = new A;
        a.x = 10; // Not OK, and frustrating
    }
}


Walter says that "this is the way C++ does it."  I don't care.  D is not C++, and this is just as frustrating in C++ as it is in D.  If B is declared in the same file as A, it's legal, but this way, it's not.  This makes it very difficult to extend classes in modules separate from the module in which the base class was declared.

And no, it can't be made public.  That completely defeats the purpose of protection attributes.

All I want to know is the single, overriding rationale for keeping the behavior like this.  "It's the way C++ does it" is not good enough.


December 18, 2005
Jarrett Billingsley wrote:
> I posted this a while ago, but the problem still has not been addressed. Mostly because Walter doesn't think it's a problem.
> 
> [file1.d]
> 
> class A
> {
>     protected int x;
> }
> 
> [file2.d]
> 
> import file1;
> 
> class B : A
> {
>     void fork()
>     {
>         x = 5; // OK
> 
>         B b = new B;
>         b. x = 8;  // OK
> 
>         A a = new A;
>         a.x = 10; // Not OK, and frustrating
>     }
> }
> 
> 
> Walter says that "this is the way C++ does it."  I don't care.  D is not C++, and this is just as frustrating in C++ as it is in D.  If B is declared in the same file as A, it's legal, but this way, it's not.  This makes it very difficult to extend classes in modules separate from the module in which the base class was declared.

I thought "protected" class members were only visible to deriving classes, why is a.x visible if B is declared in the same module as A?

> And no, it can't be made public.  That completely defeats the purpose of protection attributes.
> 
> All I want to know is the single, overriding rationale for keeping the behavior like this.  "It's the way C++ does it" is not good enough. 

This is a somewhat weird aspect of inheritance.  Basically, at all times, all a class can ever see are its own data members.  It just so happens that in this case, some of B's data members were imported from A.  The important distinction here is that B can only access this data *within the context of B*.  To do otherwise would break protection rules.  From your example, why should B have access to the protected innards of all A's just because B extends A?


Sean
December 19, 2005
"Sean Kelly" <sean@f4.ca> wrote in message news:do4rsd$h0f$1@digitaldaemon.com...
> This is a somewhat weird aspect of inheritance.  Basically, at all times, all a class can ever see are its own data members.  It just so happens that in this case, some of B's data members were imported from A.  The important distinction here is that B can only access this data *within the context of B*.  To do otherwise would break protection rules.  From your example, why should B have access to the protected innards of all A's just because B extends A?

Why should classes be able to access members of other classes defined in the same module, regardless of protection attributes?  Because it's useful. That "breaks" protection rules too, but no one complains about that.  In the same way, allowing access to protected members of base classes through base class references is useful.  All I want to know is the _downside_ of allowing this.


December 19, 2005
On Sun, 18 Dec 2005 18:50:43 -0500, Jarrett Billingsley wrote:

> "Sean Kelly" <sean@f4.ca> wrote in message news:do4rsd$h0f$1@digitaldaemon.com...
>> This is a somewhat weird aspect of inheritance.  Basically, at all times, all a class can ever see are its own data members.  It just so happens that in this case, some of B's data members were imported from A.  The important distinction here is that B can only access this data *within the context of B*.  To do otherwise would break protection rules.  From your example, why should B have access to the protected innards of all A's just because B extends A?
> 
> Why should classes be able to access members of other classes defined in the same module, regardless of protection attributes?  Because it's useful. That "breaks" protection rules too, but no one complains about that.

Sort of ... but the assumption is that things defined in the same module (source file) are 'friends' of each other. So, the same person that maintains one class also will be capable of maintaining the other classes in the same file. In this way, the 'module' scoping overrides all other scopes (but maybe not inner classes?).

>  In the
> same way, allowing access to protected members of base classes through base
> class references is useful.

Can you give us an example? And could be done in other ways? For example ...

//----------------
import file1;

// Use 'Base_A' to gain simple access to base class members.
class Base_A : A
{
}

class B : A
{
    void fork()
    {
        x = 5; // OK

        B b = new B;
        b. x = 8;  // OK

        Base_A a = new Base_A; // Not 'new A';
        a.x = 10; // Now OK
    }
}


> All I want to know is the _downside_ of allowing this.

It weakens the concept of protected. In the 'workaround' above at least it explicitly documents what I'm trying to do.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"A learning experience is one of those things that says,
 'You know that thing you just did? Don't do that.'" - D.N. Adams
19/12/2005 12:01:32 PM
December 19, 2005
Jarrett Billingsley wrote:
> "Sean Kelly" <sean@f4.ca> wrote in message news:do4rsd$h0f$1@digitaldaemon.com...
> 
>>This is a somewhat weird aspect of inheritance.  Basically, at all times, all a class can ever see are its own data members.  It just so happens that in this case, some of B's data members were imported from A.  The important distinction here is that B can only access this data *within the context of B*.  To do otherwise would break protection rules.  From your example, why should B have access to the protected innards of all A's just because B extends A?
> 
> 
> Why should classes be able to access members of other classes defined in the same module, regardless of protection attributes?  Because it's useful. That "breaks" protection rules too, but no one complains about that.

I do complain about that! Some others complain too, but it doesn't seem like Walter is gonna change it.
December 19, 2005
"Derek Parnell" <derek@psych.ward> wrote in message news:9bezpukt519x.152h73q6j874i.dlg@40tude.net...
> Sort of ... but the assumption is that things defined in the same module (source file) are 'friends' of each other. So, the same person that maintains one class also will be capable of maintaining the other classes in the same file. In this way, the 'module' scoping overrides all other scopes (but maybe not inner classes?).

Right.  (Although I think the thing with inner classes is just a bug.)

> Can you give us an example? And could be done in other ways?

Your example works, but not necessarily for all situations.  Like:

[file1.d]
module file1;

private import std.stdio;

class A
{
 this(int i)
 {
  x = i;
 }

 void something()
 {
  as.length = 5;
  for(uint i = 0; i < 5; i++)
   as[i] = new A(i + 1);
 }

 void printChildren()
 {
  foreach(A a; as)
   writefln(a.x);
 }

 protected A[] as;
 protected int x;
}


[file2.d]
module file2;

import std.stdio;
import file1;

class B : A
{
 this(int i)
 {
  super(i);
 }

 override void printChildren()
 {
  foreach(A a; as)
   writefln("From B: ", a.x); // No good
 }
}

void main(char[][] args)
{
 A a = new A(0);
 a.something();
 a.printChildren();

 B b = new B(0);
 b.something();
 b.printChildren();
}


In many of my projects, I run into similar situations - needing to override a function in a subclass which needs to access members of base class references.  And in many of my projects, I run into the same limitation. Most of the time, I can't just call the super.overriddenFunction(), because I'm changing the internal workings of the function.

> It weakens the concept of protected. In the 'workaround' above at least it explicitly documents what I'm trying to do.

I think saying that the class inherits from another class does that just fine.  Personally I think that being able to access members of base class references seems perfectly normal, and I don't see how it "weakens" protected.  It makes it better, if anything.


December 19, 2005
On Sun, 18 Dec 2005 21:34:02 -0500, Jarrett Billingsley <kb3ctd2@yahoo.com> wrote:
> "Derek Parnell" <derek@psych.ward> wrote in message
> news:9bezpukt519x.152h73q6j874i.dlg@40tude.net...
>> Sort of ... but the assumption is that things defined in the same module
>> (source file) are 'friends' of each other. So, the same person that
>> maintains one class also will be capable of maintaining the other classes
>> in the same file. In this way, the 'module' scoping overrides all other
>> scopes (but maybe not inner classes?).
>
> Right.  (Although I think the thing with inner classes is just a bug.)
>
>> Can you give us an example? And could be done in other ways?
>
> Your example works, but not necessarily for all situations.  Like:
>
> [file1.d]
> module file1;
>
> private import std.stdio;
>
> class A
> {
>  this(int i)
>  {
>   x = i;
>  }
>
>  void something()
>  {
>   as.length = 5;
>   for(uint i = 0; i < 5; i++)
>    as[i] = new A(i + 1);
>  }
>
>  void printChildren()
>  {
>   foreach(A a; as)
>    writefln(a.x);
>  }
>
>  protected A[] as;
>  protected int x;
> }
>
>
> [file2.d]
> module file2;
>
> import std.stdio;
> import file1;
>
> class B : A
> {
>  this(int i)
>  {
>   super(i);
>  }
>
>  override void printChildren()
>  {
>   foreach(A a; as)
>    writefln("From B: ", a.x); // No good
>  }
> }
>
> void main(char[][] args)
> {
>  A a = new A(0);
>  a.something();
>  a.printChildren();
>
>  B b = new B(0);
>  b.something();
>  b.printChildren();
> }
>
>
> In many of my projects, I run into similar situations - needing to override
> a function in a subclass which needs to access members of base class
> references.  And in many of my projects, I run into the same limitation.
> Most of the time, I can't just call the super.overriddenFunction(), because
> I'm changing the internal workings of the function.
>
>> It weakens the concept of protected. In the 'workaround' above at least it
>> explicitly documents what I'm trying to do.
>
> I think saying that the class inherits from another class does that just
> fine.  Personally I think that being able to access members of base class
> references seems perfectly normal, and I don't see how it "weakens"
> protected.  It makes it better, if anything.

It "weakens" in the sense that it lessens the protection that protected gives.

Your suggested change would allow an instance of a B to access "protected" members of _another_ instance of an A or B. Typically to get that access you make them "friends" i.e. put them in the same module, perhaps there is room for another protection type, but I don't think we want to modify protected.

Regan
December 19, 2005
On Sun, 18 Dec 2005 21:34:02 -0500, Jarrett Billingsley wrote:

> "Derek Parnell" <derek@psych.ward> wrote in message

[snip]

> In many of my projects, I run into similar situations - needing to override a function in a subclass which needs to access members of base class references.  And in many of my projects, I run into the same limitation. Most of the time, I can't just call the super.overriddenFunction(), because I'm changing the internal workings of the function.

I see now. If the access you want is read-only then you can document and use that explicitly. In your example add the these two methods to class A ...

 int ro_x() {return x;}
 A onApply(int i){return as[i];}

and change the overriding function in B to say ...

   writefln("From B: ", a.ro_x);

That way, the stuff in A is still runtime protected, and B (and others) can access the data in a safer read-only way.

>> It weakens the concept of protected. In the 'workaround' above at least it explicitly documents what I'm trying to do.
> 
> I think saying that the class inherits from another class does that just fine.  Personally I think that being able to access members of base class references seems perfectly normal, and I don't see how it "weakens" protected.  It makes it better, if anything.

We differ.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"A learning experience is one of those things that says,
 'You know that thing you just did? Don't do that.'" - D.N. Adams
19/12/2005 4:36:14 PM
December 19, 2005
In article <do4qi9$eam$1@digitaldaemon.com>, Jarrett Billingsley says...
>
>I posted this a while ago, but the problem still has not been addressed. Mostly because Walter doesn't think it's a problem.
>
>[file1.d]
>
>class A
>{
>    protected int x;
>}
>
>[file2.d]
>
>import file1;
>
>class B : A
>{
>    void fork()
>    {
>        x = 5; // OK
>
>        B b = new B;
>        b. x = 8;  // OK
>
>        A a = new A;
>        a.x = 10; // Not OK, and frustrating
>    }
>}

Actually this is rigth.
You don't have access to the protected members of an object you own.

b.x is visible on b because B extendes A.
a.x is NOT visible because x is protected on A.

You need to review your design.
Walter doesn't need to do anything.

Ant


December 19, 2005
Ant wrote:
> Actually this is rigth.
> You don't have access to the protected members of an object you own.
> 
> b.x is visible on b because B extendes A.
> a.x is NOT visible because x is protected on A.

Maybe I'm missing something, but I've always understood the typical protection attributes to mean:
public = anybody can see it
private = only this class/object can see it
protected = only this class/object *and its descendants* can see it

So shouldn't a child class be able to see its parent's protected members?  That's supposed to be the whole idea.  If I wanted it hidden completely, I'd use private, yes?  Or do I misunderstand his issue?

-- Chris Sauls
« First   ‹ Prev
1 2 3