Good reasons to prohibit inheritance in Java?
Solution 1
Your best reference here is Item 19 of Joshua Bloch's excellent book "Effective Java", called "Design and document for inheritance or else prohibit it". (It's item 17 in the second edition and item 15 in the first edition.) You should really read it, but I'll summarize.
The interaction of inherited classes with their parents can be surprising and unpredictable if the ancestor wasn't designed to be inherited from.
Classes should therefore come in two kinds:
Classes designed to be **extended**, and with enough documentation to describe how it should be done
Classes marked **final**
If you are writing purely internal code, this may be a bit of overkill. However, the extra effort involved in adding five characters to a class file is very small. If you are writing only for internal consumption, then a future coder can always remove the 'final' - you can think of it as a warning saying "this class was not designed with inheritance in mind".
Solution 2
You might want to make a method final so that overriding classes can't change behavior that is counted on in other methods. Methods called in constructors are often declared final so you don't get any unpleasant surprises when creating objects.
Solution 3
One reason to make a class final would be if you wanted to force composition over inheritance. This is generally desirable in avoiding tight coupling between classes.
Solution 4
There are 3 use cases where you can go for final methods.
- To avoid derived class from overriding a particular base class functionality.
- This is for security purpose, where base class is giving some important core functionality of the framework where derived class is not supposed to change it.
- Final methods are faster than instance methods, as there is no use of virtual table concept for final and private methods. So where ever there is a possibility, try to use final methods.
Purpose for making a class final:
So that no body can extend those classes and change their behavior.
Eg: Wrapper class Integer is a final class. If that class is not final, then any one can extend Integer into his own class and change the basic behavior of integer class. To avoid this, java made all wrapper classes as final classes.
Solution 5
you might want to make immutable objects (http://en.wikipedia.org/wiki/Immutable_object), you might want to create a singleton (http://en.wikipedia.org/wiki/Singleton_pattern), or you might want to prevent someone from overriding the method for reasons of efficiency, safety, or security.
Related videos on Youtube
Comments
-
cretzel about 2 years
What are good reasons to prohibit inheritance in Java, for example by using final classes or classes using a single, private parameterless constructor? What are good reasons of making a method final?
-
John Topley over 15 yearsPedantry: The default constructor is the one generated for you by the Java compiler if you don't explicitly write one in your code. You mean the no argument constructor.
-
cretzel over 15 yearsIsn't that the "implicit default constructor"?
-
John Topley over 15 years"You don't have to provide any constructors for your class, but you must be careful when doing this. The compiler automatically provides a no-argument, default constructor for any class without constructors." java.sun.com/docs/books/tutorial/java/javaOO/constructors.html – John Topley
-
-
matt b over 15 yearsThere's something I don't understand about that argument - if someone did change those calculations/constants that shouldn't change - aren't any failures due to that 100% their fault? In other words, how does the change benefit anything?
-
Anson Smith over 15 yearsYes, it's technically "their" fault but imagine someone else using the library that's not been made aware of the changes, could lead to confusion. I have always thought that that was the reason many of the Java Base classes were marked final, to stop people form altering basic functionality.
-
Eric Weilnau over 15 years@matt b - You seem to be assuming that the developer who made the change did so knowingly or that they would care that it was their fault. If someone besides me will be using my code, I will mark it final unless it is meant to be changed.
-
Eric Weilnau over 15 yearsIn my experience this is not overkill if anyone besides me will be using the code. I have never understood why Java has methods overridable by default.
-
Brett over 15 yearsTo understand some of Effective Java, you need to understand Josh's take on design. He says [something like] you should always design class interfaces as if they were a public API. I think the majority opinion is that this approach is usually too heavy and inflexible. (YAGNI, etc.)
-
DJClayworth over 15 yearsThis is actually a different usage of 'final' from the one asked about.
-
Miguel Ping over 15 yearsI believe this is a myth, since current generation VMs should be able to optimize and deoptimize as needed. I remember seeing some bencharmking this and classifying it as a myth.
-
seanalltogether over 15 yearsThe difference in code generation is not a myth, but maybe the performance gains are. As I said its a small gain, one site mentioned a 3.5% performance gain, some higher, which in most cases is not worth going all Nazi on your code.
-
Uri over 15 yearsIt is not a myth. In fact, the compiler can only inline V final methods. I am not sure if any JITs "inline" things art runtime but I doubt that it can since you may be loading a derived class later.
-
joel.neely over 15 yearsGood answer. (I can't resist pointing out that it's six characters, as there's also a space... ;-)
-
joel.neely over 15 yearsMicrobenchmark==grain-of-salt. That said, after 10B cycle warmup, avg over 10B calls shows essentially no difference under Eclipse on my laptop. Two methods returning String, final was 6.9643us, non-final was 6.9641us. That delta is background noise, IMHO.
-
notnoop over 14 yearsPlease note, that making classes final might make testing harder (harder to stub or mock)
-
Fred Haslam about 14 yearsIf the final class is writing to an interface, then mocking should not be a problem.
-
matbrgz almost 14 yearsit is very hard to remove the final on an interface you do not have source for, and being able to subclass to override a method may be essential.
-
Admin almost 10 yearsThe link to the blog post is broken. Also, do you think you could elaborate a bit more on this?
-
Jon Skeet almost 10 years@MichaelT: Fixed the link, thanks - follow it for more elaboration :) (I don't have the time to add to this right now, I'm afraid.)
-
freshtop over 9 yearsTo save people looking it up, "Design and document for inheritance or else prohibit it" is Item 17 in the second edition.
-
Rajkiran over 9 yearsNot very much convinced with your example. If that is the case, then why not make the methods and variables final instead of making the whole class final. Can you please edit your answer with the details.
-
Lucifer over 9 years@JonSkeet, The link to the blog post is broken.
-
Jon Skeet over 9 years@Kedarnath: It works for me... it was broken for a while, but it's now pointing to the correct page, on codeblog.jonskeet.uk...
-
amertkara about 9 years@ThorbjørnRavnAndersen you mean a class? An interface (or even an abstract class) with final modifier doesn't sound like a good design.
-
user1923551 about 9 yearsEven if you make all the variables and methods as final, still others can inherit your class and add extra functionality and change the basic behavior of your class.
-
Visionary Software Solutions almost 9 yearsNot this is the difference between library/framework writers and application writers. What Tom Hawtin describes as "too heavy and inflexible" becomes downright crucial when you inherit code written by others and can't deprecate any of the mistakes in the design because the original developers thought everything should be public. In general, you should always design package level final classes that implement methods on public interfaces. If you need to change the interface later, you use ADAPTER. Failure to do this means design mistakes can never be fixed once software is deployed. i.e) Java
-
Nav over 8 yearsDidn't quite understand this answer. If you don't mind, could you explain what you mean by "overriding classes can't change behaviour that is counted on in other methods"? Am asking firstly because I didn't understand the sentence, and secondly because Netbeans is recommending that one of my functions I'm calling from the constructor, should be
final
. -
Bill the Lizard over 8 years@Nav If you make a method final, then an overriding class won't be able to have its own version of that method (or it will be a compile error). That way you know that the behavior you implement in that method won't change later when someone else extends the class.
-
Siddhartha almost 7 years> If that class is not final, then any one can extend Integer into his own class and change the basic behavior of integer class. Let's say this was allowed and this new class was called
DerivedInteger
, it still doesn't change the original Integer class, and whoever usesDerivedInteger
does so at their own risk, so I still don't get why it's a problem. -
GuyPaddock over 6 yearsThe struggle I have with marking everything final by default is that it assumes a developer who didn't take the effort to make a class suitable for extension is somehow going to spend the time making sure it implements a well-designed interface to facilitate testing. Either the dev is lazy, in which case there is no interface and it's marked final, or the dev is details-oriented in which case the class supports extension and does not need to be
final
. -
Rakesh L over 6 yearsI ve started reading "Effective Java" which is mentioned in this post. It seems good to understand best practices
-
Petter Hesselberg over 2 yearsC# will warn you if you call virtual methods from a constructor. Methods called in constructors sort of mirrors this.