Classes final by default

It doesn’t matter what language was used to develop those classes. You were able to subclass them because they had been designed to be subclassable.
Or do you mean they are open just because the developers of JDK forgot to specify final modality on them or their members and just by the happy coincidence that they did use Java, having open as default, these classes are now open?

3 Likes

Let’s say some class is design well so that there is no code duplication, every method fits one purpose, the rules of structured programming and OO design are applied, etc. What you get is necessarily a class where things in subclasses can easily be overwritten to accomodate some behavior as desired. This is the essence of OO. Only very few classes in the JDK are final to prevent inner workings from functioning correctly. Those classes were deliberately declared final and not by default. But anyway, the issue is not that important to me. Other peolple may have different opinions …

I totally agree !!!

Likewise I’ve been bitten in past trying to override classes in library that have been made final, and the “closed by default” is by far the one thing that I dislike the most about Kotlin

1 Like

Actually after thinking about it quite a bit, and reading about how it doesn’t just impact deliberate overriding but also wrecks havok on AOP and and any form of “lightweight” proxying (that doesn’t involve bytecode rewriting) like for example mocking frameworks or spring aop, i think this single design choice is cause to NOT use Kotlin

It’s sad because kotlin seemed to have a lot of potential, but losing AOP and mocking is just not acceptable in this day and age.

In 22 years of java, I’ve never seen a single case where a missing “final” caused harm (unlike the inverse), so the decision to make such a drastic departure from the behavior of java is really shocking

3 Likes

Are there any plans to add an inspection to IDEA that does this? (remind me to make classes and functions open)

Reminds you to make which classes and functions open?

The problem is not so much that classes are final when they shouldn’t be, it is the lack of design for extension or general poor API design. Depending on your use case this can mean that extension is likely to break the system in unpredictable ways or a non-issue. The thing to do is to actually design classes carefully and if they should be able to be inherited they should do so. In many ways there is something to be said to provide everything as an interface and the implementation could then even be used as a delegate rather than overriding.

Yes, but doesn’t a bad design with everything final by default just makes things even worse?

If they are open by default, then the next developer that needs to extend the class will have the liberty to do it (maybe to overcome issues with that bad design).

If they are all final, that avenue is not possible, and one ends up having to:

  • find an alternative library
  • bytecode decompile and change the library
  • implement one library oneself (call about duplicated effort)

All of the alternatives are sub-optimal.

True that one probably should avoid “bad” design libraries, but then, who is the judge, and down the line there may not even exist alternatives.

So kotlin significantly penalizes developers who design their applications properly in order to coddle those which are incompetents.

That’s like forcing all cars to not go over 25m/h because some people might drive above the speed limit.

1 Like

Yes, for the people that want it that way.

We have no plans to write an inspection that would highlight every non-open class and function and suggest to make it open.

2 Likes

I think final by default is mainly a temporary problem for the time until Java is completely replaced by Kotlin. But seriously, Kotlins final by default makes weaknesses just visible - they are there even without Kotlin! And even in Java it is a bad habit to leave all classes open, what is just because of laziness. Often the code is unnecessary poor because of some framework’s limitations.

Another good example for this are all the useless interfaces just because most mocking frameworks are not powerful enough to mock final method (without additional tools like PowerMock).

And if I remember correctly, JetBrains announced plans for Kotlin meta-progamming, what should make things better in this regard (think of a nice mocking framework for Kotlin).

Mocking final methods on JVM is not that hard, it’s just frameworks that are not implementing it. All you need is to modify bytecode before it’s loaded and there are at least 3 ways that I’m aware of: java agent, custom classloader and .class file post-processing.

“temporary problem until java is completely replaced by kotlin”

Let’s be realistic, at best that “temporary” would mean MANY years and at worse it will NEVER happen (and the later is way more likely than the former).

Depending on how literal your use of “Never” is, it’s actually very probable :stuck_out_tongue_winking_eye:

I completely agree to it, making a class by default a final is degrading the OOPS power of extensiblility, at time the original author would not even think of any use case where it needs to be extended.

on one hand you are introducing extension mentions and on the other hand you are restricting inheritance.

1 Like

Its not for you but for the potential end user if you are delivering an API.

Anyway this duscussion is meaningless most users here are for open by default. Im not jave programmer i have some interest in android develepment, but as programmer i have much experience in C++ and php. I never was annoyed becouse inheritance is opened by default, but struggled when core future was closed. This key future is much reason for me to stop learning kotlin and to seek for something else.

This is not right decision. The most of classes are final/sealed in all my C#/Java/Kotlin. For example, Spring requires to have open only small portion of classes (such as marked with Configuration annotation).

final classes allow JVM to do a lot of optimizations. Moreover, it allows static processors to validate your code. In my experience, I found several issues in the legacy code after marking class final (sealed in C# terms, compiler shows me, that cast will be never succeeded).

So, kotlin language has right direction of choice: class inheritance should be disabled by default.

3 Likes

I’d love to handle things using delegation/decoration, but quite often, a class’ functions call other functions…
Let’s say a() calls b() and I want to change the behavior of b(). If I create a decorator and delegate a() to someObject.a(), it’s impl will still call someObject.b() rather than the decorator’s b()… Only way to replace b() is to override (unless the original class allowed b() to be passed in as strategy…)