• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Classes are final by default?

 
Ranch Hand
Posts: 76
3
IntelliJ IDE Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So, I've been playing around with Kotlin for a couple of days. Really starting to like the language. Something struck me as odd, however: all classes are final (not inheritable) by default.

So, to make a class non-final, you have to declare it as open. The open modifier is effectively the opposite of Java's final. Fair enough. But then I read this, in the Kotlin reference (https://kotlinlang.org/docs/reference/classes.html):

The open annotation on a class is the opposite of Java’s final: it allows others to inherit from this class. By default, all classes in Kotlin are final, which corresponds to Effective Java, Item 17: Design and document for inheritance or else prohibit it.


But doesn't this kind of go against the open-closed principle, which says that classes should be open for extension and closed for modification. So to be able to make extensions for my classes I have to remember explicitly declare the class open every time. This can get tedious.

On the other hand, it does make one think twice about the design of the class, so as to make open classes as flexible as possible. Maybe that is what they were going for. I don't know.

Thoughts? Was this a mistake by the language designers, or was it a good choice?
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here is a big discussion thread about this question Classes final by default
And also the article from Andrey Breslau (Kotlin language designer) A bit about picking defaults
 
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Making types extensible has to be a conscious choice. It's very difficult to get it right, and people actually tend to overuse inheritance when they should actually be using composition.

If anything, it was a mistake of the Java designers not to make classes final by default.
 
Ole Sandum
Ranch Hand
Posts: 76
3
IntelliJ IDE Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:Making types extensible has to be a conscious choice. It's very difficult to get it right, and people actually tend to overuse inheritance when they should actually be using composition.



Isn't this on the user of my classes, though? Opening for extension is not automatically contributing to misuse. If a user of my class ends up in a bad situation because they could not be bothered to figure out the implications when they extended my class, then surely this programmer made a huge mistake? As a library designer I always make sure to write thorough documentation. Having to remember to declare my classes open all the time really would get tedious.

I suppose I am being pedantic here, and that getting used to opening my classes really wouldn't take much effort in the end. Let alone that I already got used to declaring almost all my fields final. (Having 'val' in Kotlin is a nice relief though)
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Ole Kristian Sandum wrote:Isn't this on the user of my classes, though? Opening for extension is not automatically contributing to misuse.


No, but it *is* your responsibility to properly design a class so it can be extended correctly, which is much easier to get wrong than people think. There are a lot of hidden implications to a class being extensible.

If a user of my class ends up in a bad situation because they could not be bothered to figure out the implications when they extended my class, then surely this programmer made a huge mistake?


That doesn't mean we can't make it easier for them. Preventing the user from extending the class takes a difficult (and often poorly considered) choice out of their hands. Stricter languages and APIs are usually easier to use.

As a library designer I always make sure to write thorough documentation.


Do you document self-use? Do you document all exceptions that possible sub-classes are allowed to throw, even if your class doesn't? Do you consider that sub-classes can be cloneable or serializable, and what that implies about your class' responsibilities? Do you define what equality means? Do you avoid calling overridable methods from your constructor? Some of these are very difficult considerations. It's much easier to just limit inheritance.

Having to remember to declare my classes open all the time really would get tedious.


Then you're overusing inheritance. I can hardly remember the last time I wrote a class (not an interface) that was specifically designed to be extended.

I'm not saying inheritance is bad per se, but it's important that when it's used, the developer has taken the time to think about whether it's worth the effort.
 
Ole Sandum
Ranch Hand
Posts: 76
3
IntelliJ IDE Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I see. There are more things to consider than I initially thought. I guess I learned quite a bit from this. I feel like doing a lot of research on this subject now. Thanks a bunch
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm glad it inspired you
 
Ole Sandum
Ranch Hand
Posts: 76
3
IntelliJ IDE Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Valera Kostin wrote:Here is a big discussion thread about this question Classes final by default
And also the article from Andrey Breslau (Kotlin language designer) A bit about picking defaults


And, by the way. Thank you for the links They were really interesting discussions.
 
Ole Sandum
Ranch Hand
Posts: 76
3
IntelliJ IDE Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Another thought came to mind. Doesn't this lead to classes being substantially more difficult, if not impossible, to mock?
I know Mockito, at least, cannot be used to mock final classes.
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Another reason why you should program against interfaces.
 
Ole Sandum
Ranch Hand
Posts: 76
3
IntelliJ IDE Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:Another reason why you should program against interfaces.


Sure, but that doesn't do a lot of good if there is no interface to program against. Say, a final class that implements no interfaces. Such a class would not be possible to mock using Mockito. And, to be honest, I don't think I should have to write an interface for the sole purpose of ONE class implementing it.
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Ole Sandum wrote:And, to be honest, I don't think I should have to write an interface for the sole purpose of ONE class implementing it.


Why not? Wouldn't you say that if you find it necessary to mock a class, it's complex enough that it warrants an interface anyway? Besides, you say you only need ONE implementation, I say that's not true: you need a mock implementation as well.

Personally I don't think it's necessary to mock every single class that another class depends on. If such a class is tested sufficiently, you can use it directly in your tests for the dependent class. If it's very complex, it should have an interface regardless of how many implementations you need.
 
Ole Sandum
Ranch Hand
Posts: 76
3
IntelliJ IDE Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:Wouldn't you say that if you find it necessary to mock a class, it's complex enough that it warrants an interface anyway?


If I find it necessary to mock a class, it is because I cannot find an efficient way to trivially instantiate that class when unit testing another class that depends on it. Usually in such cases I find that the class I need to mock comes from a library that I did not make, and as such I cannot simply make an interface for it.

What I am trying to say is that when I make a class I have no way of knowing whether it will have to get mocked or not.
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
When you're dealing with third party libraries, you don't have a choice anyway. Even so, if those classes are complex enough, it might be worth it to write a facade for them which *does* implement some interface.
 
Ole Sandum
Ranch Hand
Posts: 76
3
IntelliJ IDE Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:When you're dealing with third party libraries, you don't have a choice anyway. Even so, if those classes are complex enough, it might be worth it to write a facade for them which *does* implement some interface.



Actually, you know what? That does make sense. I'm not entirely convinced, of course, but again I see I would do well to do more research on the topic.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic