digitalmars.D - Private visible?
- Lucas Goss (5/5) Jul 13 2006 Was there ever any resolve as to private being visible? I know Walter
- Bruno Medeiros (10/16) Jul 13 2006 The discussion about private being visible is pending on some research
- Lucas Goss (3/11) Jul 13 2006 Ah yes, now I remember. Thanks!
- Lars Ivar Igesund (7/13) Jul 13 2006 Did you mean accessible? Anyway, see Bruno's post, although I'm quite su...
- Dave (7/16) Jul 13 2006 Here's my take - feel free to correct:
- Lars Ivar Igesund (10/29) Jul 13 2006 Yes, that would be the sane thing, but one of the privacy problems in D,...
- Dave (2/30) Jul 13 2006 See: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/39754
- Dave (10/46) Jul 13 2006 A little too terse, I was... I tend to agree that they should be two
- Walter Bright (17/22) Jul 13 2006 The original reason why private members would be visible but not
- Dave (2/29) Jul 13 2006 Excellent - thank you.
- Dave (9/36) Jul 13 2006 I don't wish to belabor this, but it would seem that the above great
- Sean Kelly (30/54) Jul 13 2006 I would assert that mixing protection attributes on overloads is Bad
- Lucas Goss (10/30) Jul 13 2006 Interesting. But if I use a third party library:
- Dave (22/38) Jul 13 2006 accessible has been forgotten. However, there were some significant
- Lucas Goss (11/22) Jul 13 2006 That makes no sense to me (I understand what you're talking about, but
- Derek Parnell (23/47) Jul 13 2006 Error messages are good, but don't let private stuff be accessible out o...
- Ivan Senji (15/42) Jul 14 2006 If I am using a library do I really need to get error messages about
- Walter Bright (3/8) Jul 14 2006 Sometimes it is valuable to be able to say "you can't do this operation
- Ivan Senji (5/14) Jul 14 2006 OK, for a type, but would it be inconsistent if private was handled
- Walter Bright (2/19) Jul 14 2006 I don't know of a better way.
- Don Clugston (18/27) Jul 14 2006 Seems to me that it's a bit of a hack to use private for that purpose.
- Derek Parnell (8/17) Jul 14 2006 In that case, why not directly support this concept in the language rath...
- Chad J (8/29) Jul 14 2006 Just out of personal preference I agree with Derek here.
- Lucas Goss (30/33) Jul 14 2006 Can someone come up with an example or explain why this would be
- Walter Bright (3/22) Jul 14 2006 I think it's a bug that the compiler allows this. It should be illegal
- Bruno Medeiros (6/29) Jul 15 2006 Good. That should be documented in the spec then, that isn't mentioned
- Lucas Goss (3/7) Jul 15 2006 Uh, that was C++ code, sorry I didn't make it clear.
- Bruno Medeiros (6/15) Jul 16 2006 Yes, but what Walter said (about the spec) was referring to D, even if
- Lucas Goss (18/41) Jul 15 2006 Um, maybe I didn't make it clear enough, or maybe I'm not understanding....
- Walter Bright (4/6) Jul 15 2006 Yes, it is C++ and is perfectly legal C++. A more interesting question
- David Medlock (5/14) Jul 15 2006 in Java you cannot override a method with a more protected access. I
- Bruno Medeiros (9/16) Jul 16 2006 Could you post the link to that discussion? (I don't think I can easily
- David Medlock (4/24) Jul 16 2006 Not to mention you can always throw an Exception in the disallowed
- Walter Bright (5/7) Jul 16 2006 It's entitled:
- Lucas Goss (5/12) Jul 16 2006 That's what I'm trying to discover, is there a good reason it should be
- xs0 (24/41) Jul 14 2006 Consider
- =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= (23/43) Jul 14 2006 And casting back to IntNumber makes it again private. No OOP language
- Bruno Medeiros (7/52) Jul 14 2006 Agreed, it does seem that contravariant (method) protection levels
- xs0 (12/36) Jul 14 2006 No, the compiler obviously still sees them.. But as far as things like
- =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= (12/22) Jul 14 2006 Sorry, my bad. I was still thinking about the overrides.
- Dave (17/72) Jul 14 2006 With 162, it _does_ fail to compile if you move the class definitions to...
- Bruno Medeiros (16/43) Jul 14 2006 Perhaps do as suggested before, disallow overloads with different
- =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= (21/73) Jul 13 2006 IMO 'private' works quite well now. The only problem is that there's no
- Dave (21/94) Jul 13 2006 Here's an example that doesn't require FQN to expose the bug:
- =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= (4/26) Jul 13 2006 Doh, didn't see that :">
- Michael (2/7) 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. LucasThe 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. LucasDid 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:sureWas 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. LucasDid you mean accessible? Anyway, see Bruno's post, although I'm quiteit 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:See: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/39754Lars 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.
Jul 13 2006
Dave wrote:Lars Ivar Igesund wrote: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.Dave wrote:See: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/39754Lars 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.
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:Excellent - thank you.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: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: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.bugs/7649 Thanks, - DaveEveryone 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:Thank you very much for looking into this.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.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:accessible has been forgotten. However, there were some significant issues brought up with making them invisible:The original reason why private members would be visible but notdifferent 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.1) function overloading - if various overloads of a function haveoperation on certain argument types, because instead the private function will not be seen and another selected.2) function overloading - one could lose the ability to 'poison' anoverrides 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.3) function overriding - if a private function in a derived classInteresting. 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 documentationand there is no "commonFuncName".I had some more thoughts... but I lost them in the midst of otherresponsibilities. I'll see if I can remember.LucasIt 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. - DaveThat 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:Error messages are good, but don't let private stuff be accessible out of scope.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.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: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?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.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: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?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
Ivan Senji wrote:Walter Bright wrote:I don't know of a better way.Ivan Senji wrote: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?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: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 ..."); } }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
On Fri, 14 Jul 2006 19:30:19 +1000, Walter Bright <newshound digitalmars.com> wrote:Ivan Senji wrote: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, AustraliaVarious '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
Derek Parnell wrote:On Fri, 14 Jul 2006 19:30:19 +1000, Walter Bright <newshound digitalmars.com> wrote: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.Ivan Senji wrote: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.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: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:I think it's a bug that the compiler allows this. It should be illegal code, because it breaks encapsulation.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; } };
Jul 14 2006
Walter Bright wrote:Lucas Goss wrote: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#DWalter Bright wrote:I think it's a bug that the compiler allows this. It should be illegal code, because it breaks encapsulation.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; } };
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: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#DGood. 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 16 2006
Walter Bright wrote:Lucas Goss wrote: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 practice). I just wanted to make sure I'm understanding correctly. LucasWalter Bright wrote:I think it's a bug that the compiler allows this. It should be illegal code, because it breaks encapsulation.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; } };
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: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. -DavidMSo 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:Could you post the link to that discussion? (I don't think I can easily find it myself) 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#DSo 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 16 2006
Bruno Medeiros wrote:Walter Bright wrote: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. -DavidMLucas Goss wrote:Could you post the link to that discussion? (I don't think I can easily find it myself) disallows to change the protection in any way. Java has a covariant behavior, as mentioned by David. )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 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: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). LucasSo 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 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:Agreed, it does seem that contravariant (method) protection levels should not be allowed.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.He said overload, not override. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DAs 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(); ... } }
Jul 14 2006
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)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?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.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(); ... } }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: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-MattiI'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.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?
Jul 14 2006
xs0 wrote: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.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.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
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); } }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.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. xs0Reducing 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'.
Jul 14 2006
xs0 wrote: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.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); } }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.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. xs0Reducing 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'.
Jul 14 2006
Walter Bright wrote:Dave wrote:Perhaps do as suggested before, disallow overloads with different protections?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.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: http://www.digitalmars.com/drn-bin/wwwnews?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: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.Lars Ivar Igesund wrote: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.Dave wrote:See: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/39754Lars 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.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: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. - DaveDave wrote: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.Lars Ivar Igesund wrote: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.Dave wrote:See: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/39754Lars 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.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)?
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
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