Last update January 17, 2007

Private Issues



Difference (last change) (Author, normal page display)

Changed: 165c165
visibility bug
visibility bug

Table of contents of this page
Private; Seen but not Accessed   
Argument For Visible But Not Accessible   
Arguments For Not Visible Or Accessible   
Poison Example (C++)   
Other Languages   
Related Newsgroup Thread   

Private; Seen but not Accessed    

Currently private is visible but not accessible, which can be confusing to many because of how private is usually understood.

Argument For Visible But Not Accessible    

1

function overloading - if various overloads of a function have different protections, different functions will be selected even though the same arguments are presented. This can be surprising when code is moved around. If they are visible, you'll get an error message instead of silently varying behavior. -Walter

2

function overloading - one could lose the ability to 'poison' an operation on certain argument types, because instead the private function will not be seen and another selected. -Walter

3

function overriding - if a private function in a derived class overrides a public one in a base class, this overriding will not happen if the private function is invisible. Not only does this break encapsulation, it prevents the design pattern of being able to 'poison' certain operations on a class. -Walter

Sometimes it is valuable to be able to say "you can't do this operation with this type". I don't see why this ability should be restricted to C++. -Walter

Arguments For Not Visible Or Accessible    

1

I would assert that mixing protection attributes on overloads is Bad Programming. Further, I think the principle of least surprise may not be a particularly strong argument here because the truly surprising behavior seems to be that private symbols are considered at all. That the current C++ behavior has been elevated to the status of a newbie FAQ question is ample evidence here. -Sean Kelly

Error messages are good, but don't let private stuff be accessible out of scope. -Derek Parnell

If I am using a library do I really need to get error messages about private functions from that library? To me this sounds not only like a bad design of that library but also of the language that allows it.

As others said mixing various protections on different functions of the same name is most of the times a bad design. But if it isn't and it is intentional, then what is the point in getting an error that something is private. If something is private isn't it then meant not to be seen? -Ivan Senji

2

So basically intentionally exploiting the above behavior to prevent certain implicit conversions from occurring if the programmer does not have access to the base class (where it may be possible to add an 'explicit' in C++). Is this practice at all common? And how much does it apply to D, given D's far simpler overload resolution mechanism? -Sean Kelly

As it should. 'private' means 'this is mine and not yours so don't touch, okay!?' -Derek Parnell

Various 'poisoning' techniques sound a lot like C++ to me. There one can make classes that can not be constructed, can not be inherited from, can not be passed by value, cannot be allocated on stack and many different things by making something that is private. But are these techniques realistic or even possible in D? -Ivan Senji

3

Perhaps there should be some discussion of what 'private' means in D compared to C++. For example, private functions in D are not overridable, but they are in C++. I think this represents a somewhat fundamental departure from the C++ mindset, and perhaps warrants a different interpretation of how symbol resolution should be handled. Also, we have the benefit of weighing nearly 20 years of experience with the C++ mechanism, which I suspect had to be considered in purely hypothetical terms when the original decision was made. -Sean Kelly

And yet to me this sounds like a good thing. -Derek Parnell

class Number {
    public void setVal(int val) { ... }
    public void setVal(long val) { ... }
}
...
class IntNumber : Number {
    public void setVal(int val) { ... }
    private void setVal(long val) { assert(0); }
}
...
Number a = new IntNumber();
a.setVal(10L);

Now, not only does the last line compile, it also calls the wrong function and fails to fail. There is no poisoning or whatever, and the author's belief that he achieved something by declaring something private is misguided. Furthermore, allowing the private declaration above means allowing broking inherited interfaces, practically always a bug.

Reducing visibility should be forbidden, as it doesn't even work and leads to bugs.

Private members should be totally invisible, because that's the point of marking them private.

As for overloading issues, as far as I am concerned, feel free to require all methods with the same name to have the same protection; anything else is poor taste anyway. -xs0

Poison Example (C++)    

class Base {
  public:
    virtual int Number() = 0;
};
...
class Child : public Base {
  private:
    int Number() { return 1; }
};
...
Child c;
int num = c.Number(); //error: cannot access private member
Child* cp = new Child();
num = cp->Number(); //error: cannot access private member
Base* bp = new Child();
num = bp->Number(); // num = 1

Other Languages    

C#

Using a base class

class Base {
  public int Number() { return 0; }
}
...
class Child : Base {
  private int Number() { return 1; }
}
...
Child c;
int num = c.Number(); // use of unassigned variable 'c'
Child nc = new Child();
int num = nc.Number(); // num = 0

Using an interface

interface Base {
  int Number(); // interfaces can't use modifiers like private, public, etc.
}
...
class Child : Base {
  // without public it will error with:
  // error: Child does not implement interface member Number
  public int Number() { return 1; }
}
...
Child c;
int num = c.Number(); // use of unassigned variable 'c'
Child nc = new Child();
int num = nc.Number(); // num = 1

Related Newsgroup Thread    

visibility bug


FolderDiscussions
FrontPage | News | TestPage | MessageBoard | Search | Contributors | Folders | Index | Help | Preferences | Edit

Edit text of this page (date of last change: January 17, 2007 22:57 (diff))