0

Problem

I need to overwrite the method

@Override protected final void layoutChartChildren(double top, double left, double width, double height)

of the XYChart class. Obviously I'm not allowed to.

Question

Why do people declare methods as "final"? Is there any benefit in that?

Roland
  • 18,114
  • 12
  • 62
  • 93
  • "You might wish to make a method final if it has an implementation that should not be changed and it is critical to the consistent state of the object" (from [here](https://docs.oracle.com/javase/tutorial/java/IandI/final.html) ). If you say what your end-goal is, maybe a work-around can be suggested. – Itai Feb 11 '16 at 05:54
  • 1
    Thank you, end-goal doesn't matter. It's just that I don't understand why on earth someone would prevent overwriting a method. Even your example link doesn't make sense. If I subclass ChessAlgorithm and would like to start with the black player, why would someone want to prevent me from doing so? – Roland Feb 11 '16 at 07:00
  • Possible duplicate of [Reasoning for making a method final](http://stackoverflow.com/questions/5708940/reasoning-for-making-a-method-final) – fabian Feb 11 '16 at 10:41
  • For a general answer, I'd recommend starting with Josh Bloch's book "Effective Java". He talks about `final` methods in the context of API design quite extensively. The implementation of this particular method is tightly integrated with the implementation of other methods in the class, so allowing it to be overridden would greatly diminish the opportunity to change those implementation details in later releases. What it does is position the axes, invoke `layoutPlotChildren()`, position the plot and then add grid lines etc. So you should be able to change the behavior by other means. – James_D Feb 11 '16 at 12:34
  • The points of the link sillyfly provided are 1. You would allow subclassing `ChessAlgorithm` to allow for other implementations (maybe ones that play a better game). However you should enforce that all subclasses obey the rules of chess. The rules of chess state white plays first, so allowing overriding `getFirstPlayer()` would allow a subclass to break the contract of the `ChessAlgorithm` class, so you should prevent it. 2. enums are ordered, so there's already a notion of first player: `Player.values()[0]`. The class should enforce `getFirstPlayer()==Player.values()[0]`. – James_D Feb 11 '16 at 13:36

1 Answers1

2

This answer is just a verbatim quote of text by Richard Bair, one of the JavaFX API designers, which was posted on a mailing list in response to the question: "Why is almost everything in the [JavaFX] API final?"

Subclassing breaks encapsulation. That's the fundamental reason why you must design with care to allow for subclassing, or prohibit it. Making all the fields of a class public would give developers increased power -- but of course this breaks encapsulation, so we avoid it.

We broke people all the time in Swing. It was very difficult to make even modest bug fixes in Swing without breaking somebody. Changing the order of calls in a method, broke people. When your framework or API is being used by millions of programs and the program authors have no way of knowing which version of your framework they might be running on (the curse of a shared install of the JRE!), then you find an awful lot of wisdom in making everything final you possibly can. It isn't just to protect your own freedom, it actually creates a better product for everybody. You think you want to subclass and override, but this comes with a significant downside. The framework author isn't going to be able to make things better for you in the future.

There's more to it though. When you design an API, you have to think about the combinations of all things allowed by a developer. When you allow subclassing, you open up a tremendous number of additional possible failure modes, so you need to do so with care. Allowing a subclass but limiting what a superclass allows for redefinition reduces failure modes. One of my ideals in API design is to create an API with as much power as possible while reducing the number of failure modes. It is challenging to do so while also providing enough flexibility for developers to do what they need to do, and if I have to choose, I will always err on the side of giving less API in a release, because you can always add more API later, but once you've released an API you're stuck with it, or you will break people. And in this case, API doesn't just mean the method signature, it means the behavior when certain methods are invoked (as Josh points out in Effective Java).

The getter / setter method problem Jonathan described is a perfect example. If we make those methods non-final, then indeed it allows a subclass to override and log calls. But that's about all it is good for. If the subclass were to never call super, then we will be broken (and their app as well!). They think they're disallowing a certain input value, but they're not. Or the getter returns a value other than what the property object holds. Or listener notification doesn't happen right or at the right time. Or the wrong instance of the property object is returned.

Two things I really like: final, and immutability. GUI's however tend to favor big class hierarchies and mutable state :-). But we use final and immutability as much as we can.

Some information:

Community
  • 1
  • 1
jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • That's a correct answer, but "It was very difficult to make even modest bug fixes in Swing without breaking somebody." <- is a poor and vague reasoning of JavaFX developers. When I make programs in Android, I don't have that `final` issue, and nothing gets broken with the subsequent Android releases. – Eugene Kartoyev Jul 11 '18 at 17:09