1. Overview
In this tutorial, we’ll learn about the explicit API mode in Kotlin and what difference it makes to our code when it’s enabled in either Strict or Warning mode. We’ll also see how to add it to our project using the Gradle KTS, Gradle Groovy, Maven, and Command-Line Compiler approaches.
2. What Is Explicit API Mode?
Kotlin provides the explicit API setting mainly to provide library authors with tools to make library code safer, clearer, and more consistent.
In this mode, the Kotlin compiler does additional checks to ensure more explicit public API definitions. Test files are ignored as they aren’t part of the public API; the explicit API mode only applies to production code.
2.1. Visibility Modifiers
In Kotlin, the default visibility modifier for any given function or variable is public. Usually, this won’t make a lot of difference. Most of the time, we can refactor our code freely without thinking about downstream dependencies.
The explicit API requires public API to be explicitly set so that no declarations become public API unintentionally.
To demonstrate this concept, let’s write a simple class, a sum calculator:
class Calculator {
fun sum(a: Int, b: Int) = a + b
}
If we have the explicit API mode enabled, the compiler complains that neither the Calculator class nor the sum function is defining its visibility explicitly:
Visibility must be specified in explicit API mode
Let’s fix that by adding the public modifier to both:
public class Calculator {
public fun sum(a: Int, b: Int) = a + b
}
2.2. Explicit Type Specification
It’s usual to leverage Kotlin’s compiler to infer the result type of variables or functions. This technique is great for writing code in general. However, when moving to a more explicit API, the inferred type is dangerous, as we can change the type without notice, and this must never be unintentional.
The explicit API requires the public API to define the returning type explicitly so that no type is changed unintentionally.
Let’s demonstrate that concept with our sum() function. When we write it depending on the compiler to infer the type, we might write code like this:
public fun sum(a: Int, b: Int) = a + b
The compiler implicitly discovers the type to be an Int. To make the sum() function explicitly API-compliant, we must add the type explicitly:
public fun sum(a: Int, b: Int): Int = a + b
If the type is not added, the compiler will complain, of course:
Return type must be specified in explicit API mode
This rule applies to any part of the public API.
Keeping types explicit will help users of our API downstream, for example, when making a type check or cast.
2.3. Exceptions to the Rule
When the explicit API mode is enabled, some exceptions to the rules are allowed to avoid repetitive code:
- primary constructors
- properties of data classes
- property getters and setters
- overridden methods
3. Explicit API Modes
The possible explicit API modes are just two: Warning and Strict.
Both modes run the same logic, but Warning won’t crash the build – it only produces warnings.
Strict mode, on the other hand, produces errors and thus crashes the build.
4. Turning the Explicit API Mode On
To enable the explicit API mode, we must pass a flag to the compiler. When using Gradle, we can use both Kotlin and Groovy. We can also run directly in the command line compiler. Let’s take a look at all these options:
4.1. In Gradle With KTS
In our project’s build.gradle.kts, we must add the setting to the kotlin configuration block.
Here’s how we enable the Strict mode:
kotlin {
explicitApi()
// or
explicitApi = ExplicitApiMode.Strict
}
Now, let’s see how to enable the Warning mode:
kotlin {
explicitApiWarning()
// or
explicitApi = ExplicitApiMode.Warning
}
4.2. In Gradle With Groovy
In our project’s build.gradle, we must add the same setting to the kotlin configuration block.
Let’s enable the Strict mode:
kotlin {
explicitApi()
// or
explicitApi = 'strict'
}
Here’s how we can enable the Warning mode:
kotlin {
explicitApiWarning()
// or
explicitApi = 'warning'
}
4.3. In Maven
In our project’s pom.xml file, we must add the argument in the configuration section of the kotlin-maven-plugin :
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<args>
<arg>-Xexplicit-api=strict</arg>
</args>
</configuration>
</plugin>
4.4. In Command Line Compiler
And lastly, we can use use the CLI directly:
$ kotlinc MyKotlinFile.kt -Xexplicit-api=strict
Here, we’re adding the explicit-api flag to the compiler, with the value strict. The same can be done for the warning mode:
$kotlinc MyKotlinFile.kt -Xexplicit-api=warning
5. Conclusion
In this article, we learned about the explicit API mode in Kotlin and saw how it can help library maintainers keep their public API less error-prone.
We also looked at the rules that the explicit API mode imposes and learned how to enable it in our project, using Gradle KTS, Gradle Groovy, Maven and the Command Line Compiler.
As always, the source code for the examples is available on GitHub.