Beautify third-party API with Kotlin
Tags: kotlin, api, extension, thirdparty
Published: 2021-12-19 16:50:10

Scala has popularized the "Pimp my library" pattern:

>This is just a fancy expression to refer to the ability to supplement a library using implicit conversions.
>
> -- [Pimp My Library Pattern in Scala](https://www.baeldung.com/scala/pimp-my-library-pattern)

Kotlin does provide the same capability. However, it achieves it via _extension functions_. While the generated bytecode is similar to Java's static methods, the developer experience is the same as adding functions to existing types.

This approach has limitations, though. One cannot update the type hierarchy.

Imagine a library that offers a component with an open/close lifecycle. The component opens when you instantiate it, but you need to make sure to close it after usage, _e.g._, a file, a stream, etc.

Before Java 7, you had actually to close the component explicitly:

```java
Component component;
try {
    component = new Component();
    // Use component
} finally {
    component.close();
}
```

Java 7 introduced the _try-with-resource_ statement so that you can write something like this:

```java
try (Component component = new Component()) {
    // Use component
}                                                // 1
```

1. `Component` is closed here in a generated `finally` block

However, `Component` must implement `AutoCloseable`.

![AutoCloseable API class diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4e1tbpcn2ynx60p5lrsi.png)

Kotlin provides the `use()` extension function on `Closeable`.
Hence, one can replace the try-with-resource statement with a simple function call:

```kotlin
Component().use {
  // Use component as it
}                                                // 1
```

1. `Component` is closed here in a `finally` block

That being said, imagine that the library above implements neither `Closeable` nor `AutoCloseable`. We cannot use `use()`. Kotlin delegation to the rescue!

The Delegation pattern is widespread in Object-Oriented languages:

>In delegation, an object handles a request by delegating to a second object (the _delegate_). The delegate is a helper object, but _with the original context_. With language-level support for delegation, this is done implicitly by having `self` in the delegate refer to the original (sending) object, not the delegate (receiving object). In the delegate pattern, this is instead accomplished by explicitly passing the original object to the delegate, as an argument to a method.
>
> -- [Wikipedia](https://en.wikipedia.org/wiki/Delegation_pattern)


Implementing the Delegation pattern in Java requires writing a lot of boilerplate code. The more methods the original class has, the more boring it is:

```java
interface class Component {
    void a();
    void b();
    void c();
}

public class CloseableComponent extends Component implements Closeable {

    private final Component component;

    public CloseableComponent(Component component) {
        this.component = component;
    }

    void a() { component.a(); }
    void b() { component.b(); }
    void c() { component.c(); }
    public void close() {}
}
```

Kotlin supports the Delegation pattern out-of-the-box via the `by` keyword. One can rewrite the above code as:

```kotlin
interface Component {
    fun a() {}
    fun b() {}
    fun c() {}
}

class CloseableComponent(component: Component) : Component by component,
                                                 Closeable {                  // 1
    override fun close() {}
}
```

1. Delegate all calls of `a()`, `b()`, and `c()` to the underlying `component`

We can finally write the desired code:

```kotlin
CloseableComponent(RealComponent()).use {
    // Use component as it
}
```

Even better, it works with third-party code to improve an external library with this approach.

The icing on the cake, one can also call the code from a _try-with-resource_ Java statement:

```java
try (CloseableComponent component = new CloseableComponent(new RealComponent())) {
    // Use component
}
```

As I wrote above, one can do it in Java also. In general, however, the sheer amount of boilerplate code that one needs to write to implement delegation is a significant impediment. Kotlin makes it a breeze.

We miss one last step to make our code easier to write. How do we get the `CloseableComponent`? Let's create an extension function on `Component`:

```kotlin
fun Component.toCloseable() = CloseableComponent(this)
```

And now, usage is fluent:

```kotlin
RealComponent().toCloseable().use {
    // Use component
}
```

In this post, we have seen how to improve the API provided by third-party libraries. We achieved it by combining Kotlin extension functions and delegation.

**To go further:**

* [Extending third-party APIs in different languages](https://blog.frankel.ch/extending-third-party-apis/)
* [Extension functions](https://kotlinlang.org/docs/extensions.html#extension-functions)
* [The try-with-resources Statement](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html)
* [Kotlin's use](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html)
* [Delegation pattern](https://en.wikipedia.org/wiki/Delegation_pattern)
* [Kotlin's Delegation](https://kotlinlang.org/docs/delegation.html)

_Originally published at [A Java Geek](https://blog.frankel.ch/beautify-third-party-api-kotlin/) on December 19<sup>th</sup>, 2021_