digitalmars.D - Private visible?
- Lucas Goss <lgoss007 gmail.com> Jul 13 2006
- Bruno Medeiros <brunodomedeirosATgmail SPAM.com> Jul 13 2006
- Lucas Goss <lgoss007 gmail.com> Jul 13 2006
- Lars Ivar Igesund <larsivar igesund.net> Jul 13 2006
- Dave <Dave_member pathlink.com> Jul 13 2006
- Lars Ivar Igesund <larsivar igesund.net> Jul 13 2006
- Dave <Dave_member pathlink.com> Jul 13 2006
- Dave <Dave_member pathlink.com> Jul 13 2006
- Walter Bright <newshound digitalmars.com> Jul 13 2006
- Dave <Dave_member pathlink.com> Jul 13 2006
- Dave <Dave_member pathlink.com> Jul 13 2006
- Sean Kelly <sean f4.ca> Jul 13 2006
- Lucas Goss <lgoss007 gmail.com> Jul 13 2006
- Dave <Dave_member pathlink.com> Jul 13 2006
- Lucas Goss <lgoss007 gmail.com> Jul 13 2006
- Derek Parnell <derek nomail.afraid.org> Jul 13 2006
- Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> Jul 14 2006
- Walter Bright <newshound digitalmars.com> Jul 14 2006
- Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> Jul 14 2006
- Walter Bright <newshound digitalmars.com> Jul 14 2006
- Don Clugston <dac nospam.com.au> Jul 14 2006
- "Derek Parnell" <derek psych.ward> Jul 14 2006
- Chad J <gamerChad _spamIsBad_gmail.com> Jul 14 2006
- Lucas Goss <lgoss007 gmail.com> Jul 14 2006
- Walter Bright <newshound digitalmars.com> Jul 14 2006
- Bruno Medeiros <brunodomedeirosATgmail SPAM.com> Jul 15 2006
- Lucas Goss <lgoss007 gmail.com> Jul 15 2006
- Bruno Medeiros <brunodomedeirosATgmail SPAM.com> Jul 16 2006
- Lucas Goss <lgoss007 gmail.com> Jul 15 2006
- Walter Bright <newshound digitalmars.com> Jul 15 2006
- David Medlock <noone nowhere.com> Jul 15 2006
- Bruno Medeiros <brunodomedeirosATgmail SPAM.com> Jul 16 2006
- David Medlock <noone nowhere.com> Jul 16 2006
- Walter Bright <newshound digitalmars.com> Jul 16 2006
- Lucas Goss <lgoss007 gmail.com> Jul 16 2006
- xs0 <xs0 xs0.com> Jul 14 2006
- =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> Jul 14 2006
- Bruno Medeiros <brunodomedeirosATgmail SPAM.com> Jul 14 2006
- xs0 <xs0 xs0.com> Jul 14 2006
- Dave <Dave_member pathlink.com> Jul 14 2006
- xs0 <xs0 xs0.com> Jul 14 2006
- Dave <Dave_member pathlink.com> Jul 14 2006
- Bruno Medeiros <brunodomedeirosATgmail SPAM.com> Jul 14 2006
- =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> Jul 13 2006
- Dave <Dave_member pathlink.com> Jul 13 2006
- Michael <Michael_member pathlink.com> Jul 14 2006
Was there ever any resolve as to private being visible? I know Walter said he saw the value of private by default, but what about private being visible? It just seems to have dropped off the radar and I don't know if thats good or bad. Lucas
Jul 13 2006
Lucas Goss wrote:Was there ever any resolve as to private being visible? I know Walter said he saw the value of private by default, but what about private being visible? It just seems to have dropped off the radar and I don't know if thats good or bad. Lucas
The discussion about private being visible is pending on some research to be made about C++ accessibility rules. See this post and it's subthread: news://news.digitalmars.com:119/e8nrtd$366$1 digitaldaemon.com In particular Walter said: "Thanks for the reference. This rule, however, long predates Daveed's involvement with C++. I want to do a little more research on this." -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 13 2006
Bruno Medeiros wrote:The discussion about private being visible is pending on some research to be made about C++ accessibility rules. See this post and it's subthread: news://news.digitalmars.com:119/e8nrtd$366$1 digitaldaemon.com In particular Walter said: "Thanks for the reference. This rule, however, long predates Daveed's involvement with C++. I want to do a little more research on this."
Ah yes, now I remember. Thanks! Lucas
Jul 13 2006
Lucas Goss wrote:Was there ever any resolve as to private being visible? I know Walter said he saw the value of private by default, but what about private being visible? It just seems to have dropped off the radar and I don't know if thats good or bad. Lucas
Did you mean accessible? Anyway, see Bruno's post, although I'm quite sure it won't be forgotten by some of us ;) -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsivi
Jul 13 2006
Lars Ivar Igesund wrote:Lucas Goss wrote:Was there ever any resolve as to private being visible? I know Walter said he saw the value of private by default, but what about private being visible? It just seems to have dropped off the radar and I don't know if thats good or bad. Lucas
Did you mean accessible? Anyway, see Bruno's post, although I'm quite
it won't be forgotten by some of us ;)
Here's my take - feel free to correct: - accessible: the symbol can be used (accessed). Must be visible as well for the lookup (I realize this is obvious). - visible: the compiler considers the symbol during lookup even though it may not be accessible (maybe not so obvious).
Jul 13 2006
Dave wrote:Lars Ivar Igesund wrote: > Lucas Goss wrote: > >> Was there ever any resolve as to private being visible? I know Walter >> said he saw the value of private by default, but what about private >> being visible? It just seems to have dropped off the radar and I don't >> know if thats good or bad. >> >> Lucas > > Did you mean accessible? Anyway, see Bruno's post, although I'm quite sure > it won't be forgotten by some of us ;) > Here's my take - feel free to correct: - accessible: the symbol can be used (accessed). Must be visible as well for the lookup (I realize this is obvious).
Yes, that would be the sane thing, but one of the privacy problems in D, is that it has been possible to access symbols by using the FQN, even though it really isn't visible (declared to be private). As it is, I see no reason to differ between visible and accessible, IMO they're two sides of the same coin, or should be. -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsivi
Jul 13 2006
Lars Ivar Igesund wrote:Dave wrote:Lars Ivar Igesund wrote: > Lucas Goss wrote: > >> Was there ever any resolve as to private being visible? I know Walter >> said he saw the value of private by default, but what about private >> being visible? It just seems to have dropped off the radar and I don't >> know if thats good or bad. >> >> Lucas > > Did you mean accessible? Anyway, see Bruno's post, although I'm quite sure > it won't be forgotten by some of us ;) > Here's my take - feel free to correct: - accessible: the symbol can be used (accessed). Must be visible as well for the lookup (I realize this is obvious).
Yes, that would be the sane thing, but one of the privacy problems in D, is that it has been possible to access symbols by using the FQN, even though it really isn't visible (declared to be private). As it is, I see no reason to differ between visible and accessible, IMO they're two sides of the same coin, or should be.
See: digitalmars.D/39754
Jul 13 2006
Dave wrote:Lars Ivar Igesund wrote:Dave wrote:Lars Ivar Igesund wrote: > Lucas Goss wrote: > >> Was there ever any resolve as to private being visible? I know Walter >> said he saw the value of private by default, but what about private >> being visible? It just seems to have dropped off the radar and I don't >> know if thats good or bad. >> >> Lucas > > Did you mean accessible? Anyway, see Bruno's post, although I'm quite sure > it won't be forgotten by some of us ;) > Here's my take - feel free to correct: - accessible: the symbol can be used (accessed). Must be visible as well for the lookup (I realize this is obvious).
Yes, that would be the sane thing, but one of the privacy problems in D, is that it has been possible to access symbols by using the FQN, even though it really isn't visible (declared to be private). As it is, I see no reason to differ between visible and accessible, IMO they're two sides of the same coin, or should be.
See: digitalmars.D/39754
A little too terse, I was... I tend to agree that they should be two sides of the same coin but the gist of it is that they aren't in D because they aren't in C++ for (possibly obscure) reasons that might not apply to D. Everyone seems to agree that 'private' should not be accessible and the current behavior is a bug. What we're all wondering is if 'private' can also mean 'invisible' because that seems to be more intuitive. Than you don't have that extra level of complexity for lookup resolution and things like error messages describing a private interface.
Jul 13 2006
Dave wrote:Everyone seems to agree that 'private' should not be accessible and the current behavior is a bug. What we're all wondering is if 'private' can also mean 'invisible' because that seems to be more intuitive. Than you don't have that extra level of complexity for lookup resolution and things like error messages describing a private interface.
The original reason why private members would be visible but not accessible has been forgotten. However, there were some significant issues brought up with making them invisible: 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. 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. 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.
Jul 13 2006
Walter Bright wrote:Dave wrote:Everyone seems to agree that 'private' should not be accessible and the current behavior is a bug. What we're all wondering is if 'private' can also mean 'invisible' because that seems to be more intuitive. Than you don't have that extra level of complexity for lookup resolution and things like error messages describing a private interface.
The original reason why private members would be visible but not accessible has been forgotten. However, there were some significant issues brought up with making them invisible: 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. 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. 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.
Excellent - thank you.
Jul 13 2006
Walter Bright wrote:Dave wrote:Everyone seems to agree that 'private' should not be accessible and the current behavior is a bug. What we're all wondering is if 'private' can also mean 'invisible' because that seems to be more intuitive. Than you don't have that extra level of complexity for lookup resolution and things like error messages describing a private interface.
The original reason why private members would be visible but not accessible has been forgotten. However, there were some significant issues brought up with making them invisible: 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. 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. 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.
I don't wish to belabor this, but it would seem that the above great reasons for "visible but not accessible" conflict with the current behavior described here: digitalmars.D.bugs/7649 So there are probably some bugs in there, especially with regard to #3 above and #2 in Kris' post. This to me is a before 1.0 thing. Thanks, - Dave
Jul 13 2006
Walter Bright wrote:Dave wrote:Everyone seems to agree that 'private' should not be accessible and the current behavior is a bug. What we're all wondering is if 'private' can also mean 'invisible' because that seems to be more intuitive. Than you don't have that extra level of complexity for lookup resolution and things like error messages describing a private interface.
The original reason why private members would be visible but not accessible has been forgotten. However, there were some significant issues brought up with making them invisible:
Thank you very much for looking into this.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.
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.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.
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?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.
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. In hindsight, does the C++ mechanism seem optimal for C++? And is the language structure of D sufficiently similar to C++ that it is optimal for D, by extension? I realize that these are difficult questions to answer, but I don't want to close the door on the idea just yet simply because the decision for C++ involved reasons that *may* also apply to D. At the very least, it does seem clear that this behavior is confusing for novice programmers, and this is a red flag to me that the design may not be ideal. Sean
Jul 13 2006
Walter Bright wrote:The original reason why private members would be visible but not accessible has been forgotten. However, there were some significant issues brought up with making them invisible: 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. 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. 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.
Interesting. But if I use a third party library: import lib.thirdparty; ... commonFuncName() // error (declared in my module and in thirdparty) I would be dumbfounded. Especially when I look at there documentation and there is no "commonFuncName". I had some more thoughts... but I lost them in the midst of other responsibilities. I'll see if I can remember. Lucas
Jul 13 2006
Lucas Goss wrote:Walter Bright wrote:The original reason why private members would be visible but not
issues brought up with making them invisible:1) function overloading - if various overloads of a function have
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.2) function overloading - one could lose the ability to 'poison' an
function will not be seen and another selected.3) function overriding - if a private function in a derived class
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.Interesting. But if I use a third party library: import lib.thirdparty; ... commonFuncName() // error (declared in my module and in thirdparty) I would be dumbfounded. Especially when I look at there documentation
I had some more thoughts... but I lost them in the midst of other
Lucas
It will look for and use the one in your module. If it is in your library that is also imported, then you'd get something like: mylib.d(123): function mylib.baz conflicts with otherLib.baz at otherLib.d(456) Then right now you could alias or hopefully soon use the new import syntax to disambiguate. - Dave
Jul 13 2006
Dave wrote:It will look for and use the one in your module. If it is in your library that is also imported, then you'd get something like: mylib.d(123): function mylib.baz conflicts with otherLib.baz at otherLib.d(456) Then right now you could alias or hopefully soon use the new import syntax to disambiguate. - Dave
That makes no sense to me (I understand what you're talking about, but it's like a gotcha). How could my public function conflict with a private function? I think the problem is that private functions are imported into the current namespace (I'm pretty sure that's been said before). I remembered what I was thinking previously... Is there any way to make private functions only be available by fully qualified name lookup and not imported into the current namespace? Or would that be too much work? Lucas
Jul 13 2006
On Thu, 13 Jul 2006 11:37:50 -0700, Walter Bright wrote:Dave wrote:Everyone seems to agree that 'private' should not be accessible and the current behavior is a bug. What we're all wondering is if 'private' can also mean 'invisible' because that seems to be more intuitive. Than you don't have that extra level of complexity for lookup resolution and things like error messages describing a private interface.
The original reason why private members would be visible but not accessible has been forgotten. However, there were some significant issues brought up with making them invisible: 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.
Error messages are good, but don't let private stuff be accessible out of scope.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.
As it should. 'private' means 'this is mine and not yours so don't touch, okay!?'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.
And yet to me this sounds like a good thing. Maybe I am confusing visibility and accessibility here, but in my simple way of looking at things, 'private' should have the meaning nothing can reference a private member by name except for things in the same scope and things in the same module. In simple layman's terms, 'keep your grubby hands off my member' ;-) The current implementation of private in D is just about /perfect/, except for the couple of acknowledged bugs and the error messages that reveal private information. Bug 1. FQN usage ignores privacy. Bug 2. Function matching ignores privacy if a public name also exists. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 14/07/2006 10:53:38 AM
Jul 13 2006
Walter Bright wrote:Dave wrote:Everyone seems to agree that 'private' should not be accessible and the current behavior is a bug. What we're all wondering is if 'private' can also mean 'invisible' because that seems to be more intuitive. Than you don't have that extra level of complexity for lookup resolution and things like error messages describing a private interface.
The original reason why private members would be visible but not accessible has been forgotten. However, there were some significant issues brought up with making them invisible: 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.
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?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. 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.
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? I don't know what to do about 3) but is this the way to do things in D as is in C++?
Jul 14 2006
Ivan Senji wrote: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?
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++.
Jul 14 2006
Walter Bright wrote:Ivan Senji wrote: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?
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++.
OK, for a type, but would it be inconsistent if private was handled different in class and module level? I didn't mean it should be restricted to C++ but was rather wondering if there are other/better ways in D?
Jul 14 2006
Ivan Senji wrote:Walter Bright wrote:Ivan Senji wrote: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?
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++.
OK, for a type, but would it be inconsistent if private was handled different in class and module level? I didn't mean it should be restricted to C++ but was rather wondering if there are other/better ways in D?
I don't know of a better way.
Jul 14 2006
Walter Bright wrote:Ivan Senji wrote: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?
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++.
Seems to me that it's a bit of a hack to use private for that purpose. FWIW, you can also use deprecated{} to poison functions (though of course it doesn't work if -d is enabled). Of course this is a hack as well, but interestingly it catches internal use of that function, which AFAIK 'private' does not. class Something { deprecated { bool opEquals(Something q) { return false; } } } And if IFTI worked for operators, you could write: class Something { bool opEquals(A) (A q) { static assert(0, "You can't do == with type Something, because ..."); } }
Jul 14 2006
On Fri, 14 Jul 2006 19:30:19 +1000, Walter Bright <newshound digitalmars.com> wrote:Ivan Senji wrote: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?
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++.
In that case, why not directly support this concept in the language rather than use 'tricks' or side-effects to do it. If it a worthy thing then say so. -- Derek Parnell Melbourne, Australia
Jul 14 2006
Derek Parnell wrote:On Fri, 14 Jul 2006 19:30:19 +1000, Walter Bright <newshound digitalmars.com> wrote:Ivan Senji wrote: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?
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++.
In that case, why not directly support this concept in the language rather than use 'tricks' or side-effects to do it. If it a worthy thing then say so.
Just out of personal preference I agree with Derek here. To me it seems unintuitive to make private visible. My typical use of private is intended to hide something, not just make it inaccessable. Would there even be a way to make an identifier invisible? Anyhow, I'd rather private be invisible, and add a "poisoned" keyword or somesuch (better name?). Overloads by protection also seem dubious IMO.
Jul 14 2006
Walter Bright wrote: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++.
Can someone come up with an example or explain why this would be valuable? To make sure we're on the same page, we're talking about: ---- 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 ---- Is there an example where you can't subvert the poison? In this case can't we get a pointer to the base class which returns what the child class didn't want to give us (private Number)? ...Added to wiki to get better overview (it's easier for me to see rather than jumping all over the newsgroup. Feel free to edit and consolidate views into concrete and concise arguments. I'm starting to feel like a secretary... :) http://www.prowiki.org/wiki4d/wiki.cgi?PrivateIssues Lucas
Jul 14 2006
Lucas Goss wrote:Walter Bright wrote: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++.
Can someone come up with an example or explain why this would be valuable? To make sure we're on the same page, we're talking about: ---- class Base { public: virtual int Number() = 0; }; ... class Child : public Base { private: int Number() { return 1; } };
I think it's a bug that the compiler allows this. It should be illegal code, because it breaks encapsulation.
Jul 14 2006
Walter Bright wrote:Lucas Goss wrote:Walter Bright wrote: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++.
Can someone come up with an example or explain why this would be valuable? To make sure we're on the same page, we're talking about: ---- class Base { public: virtual int Number() = 0; }; ... class Child : public Base { private: int Number() { return 1; } };
I think it's a bug that the compiler allows this. It should be illegal code, because it breaks encapsulation.
Good. That should be documented in the spec then, that isn't mentioned anywhere, as far as we know. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 15 2006
Bruno Medeiros wrote:Good. That should be documented in the spec then, that isn't mentioned anywhere, as far as we know.
Uh, that was C++ code, sorry I didn't make it clear. Lucas
Jul 15 2006
Lucas Goss wrote:Bruno Medeiros wrote:Good. That should be documented in the spec then, that isn't mentioned anywhere, as far as we know.
Uh, that was C++ code, sorry I didn't make it clear. Lucas
Yes, but what Walter said (about the spec) was referring to D, even if your post was a C++ code. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 16 2006
Walter Bright wrote:Lucas Goss wrote:Walter Bright wrote: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++.
Can someone come up with an example or explain why this would be valuable? To make sure we're on the same page, we're talking about: ---- class Base { public: virtual int Number() = 0; }; ... class Child : public Base { private: int Number() { return 1; } };
I think it's a bug that the compiler allows this. It should be illegal code, because it breaks encapsulation.
Um, maybe I didn't make it clear enough, or maybe I'm not understanding. The above is C++ code that went with this code: (1) Child c; int num = c.Number(); //error: cannot access private member (2) Child* cp = new Child(); num = cp->Number(); //error: cannot access private member (3) Base* bp = new Child(); num = bp->Number(); // num = 1 So the compiler does error with the first two attempts, but the third compiles and runs fine. I was just trying to find an example of 'poisoning' a base class that you mentioned. To me it doesn't sound like very good practice (maybe that's why C# and I think Java disallow such practice). I just wanted to make sure I'm understanding correctly. Lucas
Jul 15 2006
Lucas Goss wrote:So the compiler does error with the first two attempts, but the third compiles and runs fine.
Yes, it is C++ and is perfectly legal C++. A more interesting question is should it be legal? I posed the question in comp.lang.c++.moderated, and got a couple of interesting answers.
Jul 15 2006
Walter Bright wrote:Lucas Goss wrote:So the compiler does error with the first two attempts, but the third compiles and runs fine.
Yes, it is C++ and is perfectly legal C++. A more interesting question is should it be legal? I posed the question in comp.lang.c++.moderated, and got a couple of interesting answers.
in Java you cannot override a method with a more protected access. I consider it a safeguard, so that I do not get caught in a lattice of protection attributes and inheritance. -DavidM
Jul 15 2006
Walter Bright wrote:Lucas Goss wrote:So the compiler does error with the first two attempts, but the third compiles and runs fine.
Yes, it is C++ and is perfectly legal C++. A more interesting question is should it be legal? I posed the question in comp.lang.c++.moderated, and got a couple of interesting answers.
Could you post the link to that discussion? (I don't think I can easily find it myself) ( Also, if you don't know already, C# adopts an invariant behavior: it disallows to change the protection in any way. Java has a covariant behavior, as mentioned by David. ) -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 16 2006
Bruno Medeiros wrote:Walter Bright wrote:Lucas Goss wrote:So the compiler does error with the first two attempts, but the third compiles and runs fine.
Yes, it is C++ and is perfectly legal C++. A more interesting question is should it be legal? I posed the question in comp.lang.c++.moderated, and got a couple of interesting answers.
Could you post the link to that discussion? (I don't think I can easily find it myself) ( Also, if you don't know already, C# adopts an invariant behavior: it disallows to change the protection in any way. Java has a covariant behavior, as mentioned by David. )
Not to mention you can always throw an Exception in the disallowed operations, so I don't see this as a great usage of protection attributes. -DavidM
Jul 16 2006
Bruno Medeiros wrote:Could you post the link to that discussion? (I don't think I can easily find it myself)
It's entitled: Restricting access should be illegal? posted 7/15/2006 3:38 AM on comp.lang.c++.moderated. It's an ongoing discussion, so it'd be premature to summarize here.
Jul 16 2006
Walter Bright wrote:Lucas Goss wrote:So the compiler does error with the first two attempts, but the third compiles and runs fine.
Yes, it is C++ and is perfectly legal C++. A more interesting question is should it be legal? I posed the question in comp.lang.c++.moderated, and got a couple of interesting answers.
That's what I'm trying to discover, is there a good reason it should be legal. I found the thread here (for those interested). http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/38a8bf39637180de/# Lucas
Jul 16 2006
The original reason why private members would be visible but not accessible has been forgotten. However, there were some significant issues brought up with making them invisible: 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.
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.
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.
Consider 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
Jul 14 2006
xs0 wrote: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.
And casting back to IntNumber makes it again private. No OOP language should do that. It's against the rules of polymorphism.Private members should be totally invisible, because that's the point of marking them private.
But then the compiler loses the ability to make intelligent error messages, right?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.
Really? Then how do you hide the previous method implementation? class A { protected pm() { ... } } class B : A { // ugly, isn't it :( protected pm() { assert(0); /* subclasses: do not use this */ } public pm2() { super.pm(); ... } } vs. class A { protected pm() { ... } } class B : A { public pm() { super.pm(); ... } } -- Jari-Matti
Jul 14 2006
Jari-Matti Mäkelä wrote:xs0 wrote: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.
And casting back to IntNumber makes it again private. No OOP language should do that. It's against the rules of polymorphism.
Agreed, it does seem that contravariant (method) protection levels should not be allowed.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.
Really? Then how do you hide the previous method implementation? class A { protected pm() { ... } } class B : A { // ugly, isn't it :( protected pm() { assert(0); /* subclasses: do not use this */ } public pm2() { super.pm(); ... } } vs. class A { protected pm() { ... } } class B : A { public pm() { super.pm(); ... } }
He said overload, not override. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 14 2006
Private members should be totally invisible, because that's the point of marking them private.
But then the compiler loses the ability to make intelligent error messages, right?
No, the compiler obviously still sees them.. But as far as things like overload resolution are concerned, the end result should be the same as if they didn't exist (note that this point is moot if they're all required to be at the same visibility)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.
Really? Then how do you hide the previous method implementation?
I'm not sure what you're asking here.. You can override methods as normal. You can also increase visibility, if you want, but once you do it for one method named "foo", you have to do it for all other methods named "foo" as well.class A { protected pm() { ... } } class B : A { // ugly, isn't it :( protected pm() { assert(0); /* subclasses: do not use this */ } public pm2() { super.pm(); ... } }
ugly indeed, but not necessary :)class A { protected pm() { ... } } class B : A { public pm() { super.pm(); ... } }
All methods in class B called "pm" have the same visibility, so no problem... xs0
Jul 14 2006
xs0 wrote: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.
Really? Then how do you hide the previous method implementation?
I'm not sure what you're asking here.. You can override methods as normal. You can also increase visibility, if you want, but once you do it for one method named "foo", you have to do it for all other methods named "foo" as well.
Sorry, my bad. I was still thinking about the overrides. Combining overriding + overloading may lead to very confusing code. Personally I definitely wouldn't want to touch any C++ code that overloads ints, longs and/or chars and overrides them with methods having totally random visibility unless somebody was pointing at me with a loaded shotgun. Luckily overloading is a bit easier in D. Still, it should first check that all overrides are sane and nothing weird happens when an object is called through different base classes/interfaces. -- Jari-Matti
Jul 14 2006
xs0 wrote:The original reason why private members would be visible but not accessible has been forgotten. However, there were some significant issues brought up with making them invisible: 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.
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.
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.
Consider 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);
With 162, it _does_ fail to compile if you move the class definitions to another module. If the code is all in the same module, then the assert trips. Both of these seem to work Ok to me.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.
IMHO, that may be a little strong... IIRC 'protection' is universally termed "access protection" - not just in D but when describing OOP protection generically or specifically for almost any other OOP language. In other words, it specifies 'access' not 'visibility'. I think this is the first time I've really run into big 'visibility' concerns and can't recall 'visibility' by itself requiring a redesign of either the library or client code that I've written or used. But I do tend to agree it can be unintuitive, and if things could also be made 'invisible' and not break/limit other things than I'm all for it. If it weren't for the two bugs regarding private module members not really being private, I wonder if this topic would even be a big concern right now.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
Jul 14 2006
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);
With 162, it _does_ fail to compile if you move the class definitions to another module. If the code is all in the same module, then the assert trips. Both of these seem to work Ok to me.
Are you sure? I just checked again and the assert doesn't trip, nor does it fail to compile. Here is the exact code I used: module main; import ba; void main() { Number a = new IntNumber(); a.setVal(10L); } ================== module ba; 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); } }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.
IMHO, that may be a little strong... IIRC 'protection' is universally termed "access protection" - not just in D but when describing OOP protection generically or specifically for almost any other OOP language. In other words, it specifies 'access' not 'visibility'.
Well, I've no idea what term is the exactly right one to use, but I wanted to say that outside their defining module, private stuff should have no effects at all on any other code, as if it wasn't there at all. xs0
Jul 14 2006
xs0 wrote: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);
With 162, it _does_ fail to compile if you move the class definitions to another module. If the code is all in the same module, then the assert trips. Both of these seem to work Ok to me.
Are you sure? I just checked again and the assert doesn't trip, nor does it fail to compile. Here is the exact code I used: module main; import ba; void main() { Number a = new IntNumber(); a.setVal(10L); } ================== module ba; 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); } }
Ahhh, I used 'IntNumber a = new IntNumber();' not 'Number a = new IntNumber();' (I didn't copy 'n paste). But 'a' is a 'Number' and not an 'IntNumber'. D has the same behavior as the equivalent C++ in this case. If I cast: (cast(IntNumber)a).setVal(10L); with your code then I get the expected results too.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.
IMHO, that may be a little strong... IIRC 'protection' is universally termed "access protection" - not just in D but when describing OOP protection generically or specifically for almost any other OOP language. In other words, it specifies 'access' not 'visibility'.
Well, I've no idea what term is the exactly right one to use, but I wanted to say that outside their defining module, private stuff should have no effects at all on any other code, as if it wasn't there at all. xs0
Jul 14 2006
Walter Bright wrote:Dave wrote:Everyone seems to agree that 'private' should not be accessible and the current behavior is a bug. What we're all wondering is if 'private' can also mean 'invisible' because that seems to be more intuitive. Than you don't have that extra level of complexity for lookup resolution and things like error messages describing a private interface.
The original reason why private members would be visible but not accessible has been forgotten. However, there were some significant issues brought up with making them invisible: 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.
protections?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.
I didn't get this case, what is this 'poison' design pattern?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.
Same question as above. But regardless of the answer, perhaps D should disallow the strictening of protection levels (i.e., allow only wider protection), since that seems to be inconsistent behavior from an OO and subtyping point of view? This issue was discussed a bit in a recent D.bugs thread: digitalmars.D.bugs/7649 (news://news.digitalmars.com:119/e7jv87$1a8g$1 digitaldaemon.com) In particular it was stated that the spec is a bit vague in what kind of behavior is allowed (in regards to overriding and protection levels). -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 14 2006
Dave wrote:Dave wrote:Lars Ivar Igesund wrote:Dave wrote:Lars Ivar Igesund wrote: > Lucas Goss wrote: > >> Was there ever any resolve as to private being visible? I know Walter >> said he saw the value of private by default, but what about private >> being visible? It just seems to have dropped off the radar and I don't >> know if thats good or bad. >> >> Lucas > > Did you mean accessible? Anyway, see Bruno's post, although I'm quite sure > it won't be forgotten by some of us ;) > Here's my take - feel free to correct: - accessible: the symbol can be used (accessed). Must be visible as well for the lookup (I realize this is obvious).
Yes, that would be the sane thing, but one of the privacy problems in D, is that it has been possible to access symbols by using the FQN, even though it really isn't visible (declared to be private). As it is, I see no reason to differ between visible and accessible, IMO they're two sides of the same coin, or should be.
See: digitalmars.D/39754
A little too terse, I was... I tend to agree that they should be two sides of the same coin but the gist of it is that they aren't in D because they aren't in C++ for (possibly obscure) reasons that might not apply to D. Everyone seems to agree that 'private' should not be accessible and the current behavior is a bug.
IMO 'private' works quite well now. The only problem is that there's no access control when using FQN's. I haven't yet tested all the special cases like inner classes, but overall it seems to be better now in 0.162.What we're all wondering is if 'private' can also mean 'invisible' because that seems to be more intuitive. Than you don't have that extra level of complexity for lookup resolution and things like error messages describing a private interface.
IMO more compiler logic here makes programmer more productive. I find this situation analogous to includes in C/C++ vs. imports in D. C/C++ is lacking a lot of great functionality there. I'm not that sure if it's that much slower to handle both levels of accessibility separately, but I can surely see the benefits arising from better compiler error messages. AFAICS the only argument against current behavior is that people think it's somehow "easier" to implement a compiler that does only visibility checks. Of course it's a bit annoying to see that this "bug" has been open for many years now, but Walter has been long busy working on the cool new features that have added much to the value of D. But now that D is reaching stable, maybe it's finally time to find a solution to these. IMO fixing the FQN's would be enough. Walter, could it be possible to implement these checks as a special case for FQN's if it's too difficult to form some general rules for the order of phases (access control, name lookup)? -- Jari-Matti
Jul 13 2006
Jari-Matti Mäkelä wrote:Dave wrote:Dave wrote:Lars Ivar Igesund wrote:Dave wrote:Lars Ivar Igesund wrote: > Lucas Goss wrote: > >> Was there ever any resolve as to private being visible? I know Walter >> said he saw the value of private by default, but what about private >> being visible? It just seems to have dropped off the radar and I don't >> know if thats good or bad. >> >> Lucas > > Did you mean accessible? Anyway, see Bruno's post, although I'm quite sure > it won't be forgotten by some of us ;) > Here's my take - feel free to correct: - accessible: the symbol can be used (accessed). Must be visible as well for the lookup (I realize this is obvious).
D, is that it has been possible to access symbols by using the FQN, even though it really isn't visible (declared to be private). As it is, I see no reason to differ between visible and accessible, IMO they're two sides of the same coin, or should be.
sides of the same coin but the gist of it is that they aren't in D because they aren't in C++ for (possibly obscure) reasons that might not apply to D. Everyone seems to agree that 'private' should not be accessible and the current behavior is a bug.
IMO 'private' works quite well now. The only problem is that there's no access control when using FQN's. I haven't yet tested all the special cases like inner classes, but overall it seems to be better now in 0.162.What we're all wondering is if 'private' can also mean 'invisible' because that seems to be more intuitive. Than you don't have that extra level of complexity for lookup resolution and things like error messages describing a private interface.
IMO more compiler logic here makes programmer more productive. I find this situation analogous to includes in C/C++ vs. imports in D. C/C++ is lacking a lot of great functionality there. I'm not that sure if it's that much slower to handle both levels of accessibility separately, but I can surely see the benefits arising from better compiler error messages. AFAICS the only argument against current behavior is that people think it's somehow "easier" to implement a compiler that does only visibility checks. Of course it's a bit annoying to see that this "bug" has been open for many years now, but Walter has been long busy working on the cool new features that have added much to the value of D. But now that D is reaching stable, maybe it's finally time to find a solution to these. IMO fixing the FQN's would be enough. Walter, could it be possible to implement these checks as a special case for FQN's if it's too difficult to form some general rules for the order of phases (access control, name lookup)?
Here's an example that doesn't require FQN to expose the bug: module foo; void bar(int i) { printf("bar(int)\n"); } private void bar(char[] str) { printf("bar(char[]): %s\n",cast(char*)str); } module main; import foo; void main() { bar("test"); } If you comment bar(int) out then it issues the correct compiler message otherwise it happily prints what you'd expect if bar(char[]) was not private. - Dave
Jul 13 2006
Dave wrote:Here's an example that doesn't require FQN to expose the bug: module foo; void bar(int i) { printf("bar(int)\n"); } private void bar(char[] str) { printf("bar(char[]): %s\n",cast(char*)str); } module main; import foo; void main() { bar("test"); } If you comment bar(int) out then it issues the correct compiler message otherwise it happily prints what you'd expect if bar(char[]) was not private.
Doh, didn't see that :"> -- Jari-Matti
Jul 13 2006
Yeah C# has this - its called public readonly. I would like to see it too. In article <e95nsi$2vkf$1 digitaldaemon.com>, Lucas Goss says...Was there ever any resolve as to private being visible? I know Walter said he saw the value of private by default, but what about private being visible? It just seems to have dropped off the radar and I don't know if thats good or bad. Lucas
Jul 14 2006









Lucas Goss <lgoss007 gmail.com> 