I was wondering why Java has been designed without the frienddirective that is available in C++ to allow finer control over which methods and instance variables are available 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.
Related
Yesterday in an Interview I was asked
How Does Encapsulation works internally ?
I was really confused because as per me Encapsulation is simply
"The state of a class should only be accessed through its public interface."
but when it comes to internal working I ran out of words.So if anyone can explain that it would be so helpful.
I agree with commenters that asking for clarifications is a good idea - good questions can be even better than good answers, and allow you to ensure that you are actually answering what they think that they are asking.
In this case, I assume that they wanted you to explain how Java ensures that programmers do not violate encapsulation. This involves
built-in syntax and semantics for marking fields / methods as public, private, protected, or package-protected.
compiler checks to ensure that these are not violated
(external) tools available to detect code smells relating to encapsulation, such as calls to overridable methods from within a constructor.
(somewhat more far-fetched) no direct access to program memory, making, for example, reinterpret-casts such as found in C / C++ unavailable in Java; this also preserves encapsulation.
You could have ensured that this is what they wanted by asking "are you referring to how Java ensures that programmers do not violate encapsulation, that is, that they do not access the state of objects except through their public interface?"
Additional answers come to mind:
use of meaningful comments, easily accessible via JavaDoc both in-IDE and as browsable documentation, that allow programmers to understand how classes are meant to be used and composed.
strong coding conventions that enforce encapsulation, such as setting fields to the most restrictive access possible, and only making public those parts that should actually be public.
Some class names are so "generic" that they are often found in several different packages, including in libraries and application code. Some examples:
Comment
Component
Factory
Location
Region
In my IDE, attempting to auto-complete the import for a class like one of these summons several competing suggestions.
When naming classes, is it a good idea to avoid class names already used elsewhere?
For some of these examples, I would imagine that using such class name is discouraged because it is simply not meaningful enough (e.g. Factory), but I am wondering whether it is discouraged to use a class name because it is used (frequently) elsewhere.
You should use class names where they make the most sense for you. None of the names above that you've proposed are off limits, and there's no reason why you can't use them (assuming a language that supports namespaces and can avoid naming conflicts in this way).
However, you may consider drilling down to class names that are more specific and precise, which will better describe the meaning of the objects in your code. For example:
Instead of Comment: LineComment or BreakComment could easily be class names in a compiler project where you would like to create semantic blocks for comments.
Instead of Component: ListComponent, CalendarComponent, or ViewComponent make particular sense when implementing a UI library where you have class-based components.
Instead of Factory: PizzaFactory makes more sense if you're trying to make pizzas!
Instead of Location: GeographicLocation or SemanticLocation makes more sense when implementing a directions based navigation app, and you're trying to distinguish between '45 deg N, 77 deg W' and 'next to the pizza place'.
Region: CodeRegion could be used in a compiler, and GeographicRegion could be used in a Maps app.
If you're afraid to be specific, namespaces and packages help. However, there is nothing discouraging you from using the same name for a class as another package where it makes sense. The class names specifically aren't copyrighted, and most IDEs now are smart enough to make distinctions between what packages you're referring to when using autocompletion.
For the most part, specificity is helpful in assisting other developers to read your code, which every developer can appreciate!
Comment, Region, and Location seem fine. Personally, so subjectively, Component and Factory are definitely too common to use but objectively I can't think of any conventional reason not to use them as names. I'd definitely try and couple those names with their respective usage, for example; TaskFactory, WidgetComponent, ButtonFactory, etc.
Depends if we are talking about business or technical part.
In technical part: using common names is actually a way to let others know about the patterns used, Factory is a good example - when you see a class named like SomethingFactory, you can expect a Factory Pattern. It goes further to frameworks, libraries etc. - SomethingAutoConfiguration with Spring-Boot, SomethingEntity with JPA, I think with frontend frameworks (React, Angular) Component is a really common word. So ye, by all means, use them, as long as you use them correctly.
In business part: simple, if those words describe your business domain, then by all means use them. Don't try to invent some fancy names (or thesaurus!) just because the words seem common, it's your business domain - it's sacred.
The EBCO is a pretty known idiom in C++, here a few links:
EBCO on cppreference.com
EBCO on WikiBooks
EBCO on the web
A citation from one of the above mentioned links:
Allows the size of an empty base subobject to be zero.
The reason and intent of this idiom is quite clear and so is the way it works (or at least, I did my best to understand it in my past).
Anyway, just for the sake of curiosity, I was guessing if there exists something similar to the EBCO in Java.
I mean, do I have any benefit in treating base empty classes differently (if yes, I'd like to know what differently means in this case), or it simply doesn't matter what I do with them?
As an example, it is possible to define classes that offer only static data members and static member methods, so theoretically there would be room for such an optimization.
Anyway, I have absolutely no idea if it makes sense to natter about that when one is dealing with a language like Java...
It's been told me (and I have seen this statement in a few other places) that it's not recommended to store your constants in a separate class in Java, in order to use them in the other classes. But I haven't seen anywhere WHY is it so. What is the reason I should not store them in their own interface/class?
I came from C to Java and in C i would just make a .h file where i defined constants with #define
Constants in a dedicated file are frowned upon for stylistic reasons. Having a class dedicated to constants can encourage developers to add increasing numbers of unrelated (undocumented?) constants to a file that slowly bloats out of control.
By contrast, having constants associated with the classes they are related to is a more scalable and readable design.
So you can be an engineer and measure constants and their locations as a technical choice. This is great and fine when you work on performance critical systems or on cool small snippets. Once your application tends to grow however, it becomes harder and harder to grasp the business requirements and end-user needs reflected in the code.
So instead of thinking about style -- separate class, properties file or nested inside a class -- I tend to follow domain driven design -- if the set of constants exclusively belong to a specific class (entity), nest the constants; if the concept touches more than one of the entities in your domain model, feel free to make it a separate entity.
And please do remember, that since Java 5, you do have enums at your disposal.
A separate constants class is not object-oriented design. In OO, a class (or interface) represents a contract, and a class which only contains constants does not define any contract.
Another object-oriented consideration is that a separate constants class encourages misuse of inheritance. Inheritance is supposed to indicate that a class fully adheres to the contract defined by another class or interface. Inheritance should not be used just to share functionality or constants; that's what public methods and fields are for. Thus, this code is incorrect:
class SomeApplicationClass
implements ScrollPaneConstants // Incorrect, import ScrollPaneConstants instead
Issue is that they should be living outside of your source code entirely. You should be using something like Apache Commons Config, or at least loading from a .properties file.
I will also note that I'm interpreting "single" with respect to a reasonable scope. For instance, there should not be one Config file for all Java developers used stored on Google's servers with a request form for modifying. There probably should not be done for your entire code base; however, per UOR or package is a reasonable scope, and is the one I use in practice.
The open-closed principle states that "Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification".
However, Joshua Bloch in his famous book "Effective Java" gives the following advice: "Design and document for inheritance, or else prohibit it", and encourages programmers to use the "final" modifier to prohibit subclassing.
I think these two principles clearly contradict each other (am I wrong?). Which principle do you follow when writing your code, and why? Do you leave your classes open, disallow inheritance on some of them (which ones?), or use the final modifier whenever possible?
Frankly I think the open/closed principle is more an anachronism than not. It sems from the 80s and 90s when OO frameworks were built on the principle that everything must inherit from something else and that everything should be subclassable.
This was most typified in UI frameworks of the era like MFC and Java Swing. In Swing, you have ridiculous inheritance where (iirc) button extends checkbox (or the other way around) giving one of them behaviour that isn't used (I think it's its the setDisabled() call on checkbox). Why do they share an ancestry? No reason other than, well, they had some methods in common.
These days composition is favoured over inheritance. Whereas Java allowed inheritance by default, .Net took the (more modern) approach of disallowing it by default, which I think is more correct (and more consistent with Josh Bloch's principles).
DI/IoC have also further made the case for composition.
Josh Bloch also points out that inheritance breaks encapsulation and gives some good examples of why. It's also been demonstrated that changing the behaviour of Java collections is more consistent if done by delegation rather than extending the classes.
Personally I largely view inheritance as little more than an implemntation detail these days.
I don't think the two statements contradict each other. A type can be open for extension and still be closed for inheritance.
One way to do this is to employ dependency injection. Instead of creating instances of its own helper types, a type can have these supplied upon creation. This allows you to change the parts (i.e. open for extension) of the type without changing the type itself (i.e. close for modification).
In open-closed principle (open for extension, closed for modification) you can still use the final modifier. Here is one example:
public final class ClosedClass {
private IMyExtension myExtension;
public ClosedClass(IMyExtension myExtension)
{
this.myExtension = myExtension;
}
// methods that use the IMyExtension object
}
public interface IMyExtension {
public void doStuff();
}
The ClosedClass is closed for modification inside the class, but open for extension through another one. In this case it can be of anything that implements the IMyExtension interface. This trick is a variation of dependency injection since we're feeding the closed class with another, in this case through the constructor. Since the extension is an interface it can't be final but its implementing class can be.
Using final on classes to close them in java is similar to using sealed in C#. There are similar discussions about it on the .NET side.
I respect Joshua Bloch a great deal, and I consider Effective Java to pretty much be the Java bible. But I think that automatically defaulting to private access is often a mistake. I tend to make things protected by default so that they can at least be accessed by extending the class. This mostly grew out of a need to unit test components, but I also find it handy for overriding the default behavior of classes. I find it very annoying when I'm working in my own company's codebase and end up having to copy & modify the source because the author chose to "hide" everything. If it's at all in my power, I lobby to have the access changed to protected to avoid the duplication, which is far worse IMHO.
Also keep in mind that Bloch's background is in designing very public bedrock API libraries; the bar for getting such code "correct" must be set very high, so chances are it's not really the same situation as most code you'll be writing. Important libraries such as the JRE itself tend to be more restrictive in order to ensure that the language is not abused. See all the deprecated APIs in the JRE? It's almost impossible to change or remove them. Your codebase is probably not set in stone, so you do have the opportunity to fix things if it turns out you made a mistake initially.
Nowadays I use the final modifier by default, almost reflexively as part of the boilerplate. It makes things easier to reason about, when you know that a given method will always function as seen in the code you're looking at right now.
Of course, sometimes there are situations where a class hierarchy is exactly what you want, and it would be silly not to use one then. But be scared of hierarchies of more than two levels, or ones where non-abstract classes are further subclassed. A class should be either abstract or final.
Most of the time, using composition is the way to go. Put all the common machinery into one class, put the the different cases into different classes, then composit instances to have working whole.
You can call this "dependency injection", or "strategy pattern" or "visitor pattern" or whatever, but what it boils down to is using composition instead of inheritance to avoid repetition.
The two statements
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
and
Design and document for inheritance, or else prohibit it.
are not in direct contradiction with one another. You can follow the open-closed principle as long as you design and document for it (as per Bloch's advice).
I don't think that Bloch states that you should prefer to prohibit inheritance by using the final modifier, just that you should explicitly choose to allow or disallow inheritance in each class you create. His advice is that you should think about it and decide for yourself, instead of just accepting the default behavior of the compiler.
I don't think that the Open/closed principle as originally presented allows the interpretation that final classes can be extended through injection of dependencies.
In my understanding, the principle is all about not allowing direct changes to code that has been put into production, and the way to achieve that while still permitting modifications to functionality is to use implementation inheritance.
As pointed out in the first answer, this has historical roots. Decades ago, inheritance was in favor, developer testing was unheard of, and recompilation of the codebase often took too long.
Also, consider that in C++ the implementation details of a class (in particular, private fields) were commonly exposed in the ".h" header file, so if a programmer needed to change it, all clients would require recompilation. Notice this isn't the case with modern languages like Java or C#. Besides, I don't think developers back then could count on sophisticated IDEs capable of performing on-the-fly dependency analysis, avoiding the need for frequent full rebuilds.
In my own experience, I prefer to do the exact opposite: "classes should be closed for extension (final) by default, but open for modification". Think about it: today we favor practices like version control (makes it easy to recover/compare previous versions of a class), refactoring (which encourages us to modify code to improve design, or as a prelude to introducing new features), and developer testing, which provides a safety net when modifying existing code.