# Public API challenges in Kotlin

DevFeed: [Public API challenges in Kotlin](<https://devfeed.tech/articles/public-api-challenges-in-kotlin-20954.md>)

Original publisher: [Read original article](<https://jakewharton.com/public-api-challenges-in-kotlin/>)

Published: 2019-11-21T00:00:00Z

Content type: article

Language: en

Sources: [Jake Wharton](<https://devfeed.tech/sources/jake-wharton.md>)

Topics: [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [API](<https://devfeed.tech/topics/api.md>), [Java](<https://devfeed.tech/topics/java.md>)

Tags: [api](<https://devfeed.tech/tags/api.md>), [blog-post](<https://devfeed.tech/tags/blog-post.md>), [java](<https://devfeed.tech/tags/java.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>)

## AI overview

The article examines challenges in porting a library type from Java to Kotlin while preserving source and binary compatibility. It focuses on Kotlin data classes, generated component and copy methods, constructor compatibility, and the effects of adding properties such as nickname.

## Source excerpt

Kotlin is justifiably lauded for its language features compared to today's Java. It has constructs which allow expressing common patterns with more concise alternatives. An overused example in every intro-to-Kotlin talk or blog post is comparing a Java "POJO" to a Kotlin data class. Here's yet another one of those comparisons, but bear with me as it will be used to illustrate the points in this post. public final class Person { private final @NonNull String name; private final int age; public Person(@NonNull String name, int age) { this.name = name; this.age = age; } public @NonNull String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "Person(name=" + name + ", age=" + age + ')' } @Override public boolean equals(@Nullable Object o) { if (o == this) return true; if (!(o instanceof Person)) return false; Person other = (Person) o; return name.equals(other.name) && age == other.age } @Override public int hashCode() { return Objects.hash(name, age); } } data class Person( val name: String, val age: Int ) Let us assume that this Person type is exposed in a library. As a result, evolving its public API needs to be done in a way that's source and binary-compatible with previous versions. This post will cover some of the challenges of porting a library containing types like Person from Java to Kotlin while maintaining the required flexibility and exposing the correct conventions to each language. Binary Compatibility What changes are necessary in order to add a new property, nickname, to Person in a binary-compatible way? For the manually-written Java type we add a new field, getter, and constructor parameter. In order to maintain compatibility, we retain the old constructor signature for old callers. public final class Person { private final @NonNull String name; + private final @Nullable String nickname; private final int age; - public Person(@NonNull String name, int age) { + public Person(@NonNull String name,