On Tuesday, May 15, 2018 06:38:04 KingJoffrey via Digitalmars-d wrote: > On Tuesday, 15 May 2018 at 05:59:44 UTC, Mike Parker wrote: > > You can keep your grouping and get your strict encapsulation > > like so: > > > > // foo/bar/baz/package.d > > module foo.bar.baz; > > public import > > > > foo.bar.baz.a, > > foo.bar.baz.b, > > foo.bar.baz.c, > > foo.bar.baz.funcs; > > > > The client need neither know nor care that everything is in > > separate modules and you get your strict encapsulation. You can > > still share items between modules via package protection, and > > within specific package hierarchies via package(packageName). > > And even better, you now have less code per module to reason > > about (re: one of your earlier arguments against the current > > behavior). > > Fine. If I take your solution above, and ensure that every class, > goes into it's own module, and that a module containing a class, > contains nothing other than a single class (i.e no free > functions), then sure, I end up where I am now, with C++/Java/C# > - i.e a good place, where I feel comfortable. My declared > interface is respected. > > Why do I need D then?
I honestly don't see how D deals with private should be a major factor in deciding what language to use. Even if you see how D handles private to be negative, if its other features aren't appealing enough to make you want to use it in spite of what's going on with private, I don't see why what happens with private matters. And even if private worked the way you want it to, I don't see why that would make anyone want to use the language over C++ or Java or whatnot. How stuff like private, package, and friends are dealt with certainly has an impact on a language, but it's just one piece of many, and I would expect most people to think that it was a relatively small piece of the puzzle such that it would not be a major deciding factor in whether they use the language, whether they like what was done with access levels or not. > i.e. under what circumstances, would I want > to put something extra into the module, so that it can abuse the > declared interface of my class? The declared interface to your class is what's presented to everything outside of your module. Everything inside the module has full access just like any friend would in C++. That's basically how you have to think about it. As long as you insist that the class itself is the barrier, then you're never going to be anything but unhappy with D's approach. > Can you give me some examples? The prime one is unit tests. The fact that they can access the private variables is invaluable for testing the state of an object. In C++, I have always have to make all of the tests friends of the class so that they can access the internals for testing. In D, I don't have to worry about any of that, and the tests don't affect the public interface of the class at all. Also, there are plenty of cases where it's nice to be able to have private functions which can access the internals of a class - and you don't necessarily want them to be members of the class. This is particularly true when the class is templated. e.g. dxml provides a fairly simply public API in dxml.parser, but it has lots of private helper functions which access the members of the struct. They operate on stuff that isn't supposed to be publicly available, and it's cleaner to have them outside the struct where they can be tested separately from the struct. Also, why would I necessarily care if something else in the same module can access the private members of a struct or class? If they're associated closely enough to be put in the same module, then there's frequently no reason to care if they access the private members or not, and as long as you're dealing with stuff like getters and setters, unless they're doing extra work other than simply encapsulating access to a member variable, there really isn't a reason why it would be a problem for other stuff in the module to access the member variable directly. Everything in the module goes together, and you can easily change anything in there if you need to due to something changing in the internals of the struct or class, and it won't affect the public API. Everything in the module is internal. Particularly when you're talking about private functions, whether something is in the class itself or in the module is an implementation detail and largely irrelevant. And if you have a public free function that can access the class' internals, well that function is associated with the class by being in the same module just like a friend function would be, and you get all of the benefits that you'd get with a friend function without having to explicitly declare everything as friends. So, all of the same reasoning as to why you'd want a friend function applies to why it can be valuable to have something in the same module access the internals of a class. The only cost is that you can't declare something not to be a friend and have it be in the same module, and you can't declare it to be a friend when it's in another module (though package does provide similar functionality). The assumption is that anything that goes in the same module can either reasonably be treated as friends, or it doesn't matter if they are. Basically all of the same arguments that you're giving against having everything in the module being treated as friends of each other can be given against having friends in the first place. It's just that D makes it implicit within the module. - Jonathan M Davis
