Search code examples
nullablekotlinkotlin-extension

Kotlin- Extension functions and platform types?


I want to add two extension functions to ResultSet that gets a value as a LocalDate.

fun ResultSet.getLocalDate(colName: String) = getDate(colName)?.toLocalDate()
fun ResultSet.getLocalDate(colIndex: Int) = getDate(colIndex)?.toLocalDate()

The problem is getDate() returns a Date!, and obviously I could get a null error without the ?. call before toLocalDate(). But then anyone using this extension must use the result as a LocalDate? rather than a LocalDate!.

Is there any way I can maintain the platform type for consistency's sake? And let the user of the extension function decide if it is allowed to be nullable or not? Or am I looking at this wrongly as an inconvenience rather than a feature?


Solution

  • Look at it from a different angle: if you could make your functions return a value of platform type LocalDate!, Java unsafe nullability would spread to the functions usages in your Kotlin code: they would return null at any time, possibly unexpected to the caller using the return value as non-null.

    Kotlin, in turn, is null-safe and it won't allow passing null silently to somewhere where it will cause an NPE. Instead, every value is either passed around as nullable or passes non-null check or assertion.

    Platform types are non-denotable in the language, this is just a way of dealing with unsafe Java nullability (simply treating all Java values as nullable wouldn't work). They provide you a way to state that you believe that this call to Java code won't return null: when you treat T! as T, an assertion is generated to check it. Otherwise you work with platform type T! as with nullable T?.

    Null safety is one of the key points in Kotlin language design, and it makes you decide for each value in your Kotlin code whether it is nullable or not.

    You have two options for API design:

    • Return a non-null value, checking the nullability inside your function
    • Return nullable value and thus warn the caller about possible null

    However, if a function has semantics allowing the caller to assume that it won't return null in some conditions, you can make a wrapper function that makes the assertion. This is feasible if coupled with additional logic or fallback, otherwise it will hardly be more concise than the assertion (!!) at call site.