Why friend directive is missing in Java?
I was wondering why Java has been designed without the friend
directive that is available in C++ to allow finer control over which methods and instance variables are a开发者_运维百科vailable from outside the package in which a class has been defined.
I don't see any practical reason nor any specific drawback, it seems just a design issue but something that wouldn't create any problem if added to the language.
Here are a few reasons off the top of my head:
- friend is not required. It is convenient, but not required
- friend supports bad design. If one class requires friend access to another, you're doing it wrong. (see above, convenient, not required).
- friend breaks encapsulation. Basically, all my privates are belong to me, and that guy over there (my friend).
In general i think it was because of the added cognitive complexity and low number of cases in which it creates an improvement.
I would say that the extremely huge number of lines of java in production at this moment can attest that the friend
keyword is not really a big loss :).
Please see @dwb's answer for some more specific reasons.
Only a very naive and inexperienced programmer would advocate against friends. Of course it can be misused, but so can public data, yet that capability is provided.
Contrary to popular opinion, here are many cases, in particular for infrastructure capabilities, where friend access leads to BETTER design, not worse design. Encapsulation is often violated when a method is FORCED to be made public when it really shouldn't be, but we are left with no choice because Java does not support friends.
In addition to the aforementioned package visibility, Java also offers inner and anonymous classes which are not only friends by default, but also automatically have a reference to the containing class. Since creating such helper classes is probably the only reasonable way to use friend
in C++, Java doesn't need it since it has another mechanism for that. Iterators are a very good example of this.
Completely agree with spaceghost's statement in his answer
Contrary to popular opinion, here are many cases, in particular for infrastructure capabilities, where friend access leads to BETTER design, not worse design.
My example is simple - if a class A has to provide a special "friend" interface to class B in java we have to place them into the same package. No exceptions. In that case if A is a friend of B and B is a friend of C, A has to be a friend of C which isn't always true. This "friendship transitivity" breaks encapsulation more then any problems which C++ friendship could lead to.
Why not simply think that Java requires friend classes to be co-located ? The package-private visibility allows everyone from the same package to access those members. So you're not only limited to explicitly declared friends, but you allow any (existing or future) friend to alter some members that are specifically designed for this purpose (but not your private stuff). You're still able to fully rely on encapsulation.
Just to add to the other answers:
There is the default package visibility in Java. So, you could call all classes in the same package neighbors. In that case you have explicit control of what you show to the neighbors - just members with package visibility.
So, it's not really a friend but can be similar. And yes, this too leads to bad design...
In my opinion some kind of friend feature (not necessarily very similar to C++'s) would be very helpful in some situations in Java. Currently we have package private/default access hacks to allow collaboration between tightly coupled classes in the same package (String
and StringBuffer
for instance), but this opens the private implementation interface up to the whole package. Between packages we have evil reflection hacks which causes a whole host of problems.
There is a bit of an additional complication in does this in Java. C++ ignores access restrictions whilst resolving function overloads (and similar) - if a program compiles #define private public
shouldn't do anything. Java (mostly) discards non-accessible members. If friendship needs to be taken into account then the resolution is more complicated and less obvious.
精彩评论