DEV Community

Discussion on: Common Java patterns in Kotlin

Collapse
 
jillesvangurp profile image
Jilles van Gurp

There are a few more things.

The builder pattern is basically obsolete with Kotlin because of several language features:

  • You can have blocks with a receiver. So instead of chaining setters, you can simply assign values to properties in a block with a receiver. This is also the basis for creating internal DSLs in Kotlin; which is much nicer than having a builder.
  • If you have a legacy Java builder, you can use the apply extension function on it and get some of the benefits that way. It basically removes the need for chaining calls like you would with a builder.
  • Functions and constructors can have arguments with default values. So instead of having gazillions of constructors, you simply have just one with sensible defaults for the things you want. Instead of needing a builder, you simply just call the constructor with the right arguments and rely on defaults for most of them.
  • Named arguments ensure that such constructor or function calls remain readable. Intellij offers a nice feature to add names to arguments. Such code is also more robust against method signature changes over time.
  • Data classes have a copy constructor where you can override values. This allows you to have immutable objects that you can easily create variants of by copying a prototype.

java.util.Optional is obsolete because you have nullable types in Kotlin and strong guarantees for that.

Inheritance is basically not needed anymore because you have extension functions and interface delegation. E.g. you can implement the Map interface and delegate to a mapOf() instead of extending some Map implementation. Extension functions work on classes, interfaces, and even type aliases. So you can trivially add new functions to existing types instead of having to extend types to be able to add stuff. This also works with things in the Kotlin or Java standard libraries. Even final classes.