kotlin: extension methods and null receiver
Asked Answered
H

4

14

In lombok extension method obj.method() is a syntax sugar for SomeUtil.method(obj). It allows for obj be null.

Kotlin extensions methods are resolved statically so I assume it's the same syntactic sugar. But when I wrote

fun Any.stringOrNull() = this?.toString()

I got a warning about unnecessary safe call on non-null receiver. Does that mean I can't call extension functions on null objects like with Lombok?

Hanes answered 24/1, 2018 at 17:2 Comment(0)
C
19

You can call it on a nullable object if you define it to be an extension on a nullable type:

fun Any?.stringOrNull() = ...

Otherwise, like with any other method, you'd have to use the safe call operator.

Chondrite answered 24/1, 2018 at 17:5 Comment(0)
S
14

You can create extensions on nullable receiver types. In your example, it has to be Any? instead of Any which would not allow null, see the docs:

Nullable Receiver

Note that extensions can be defined with a nullable receiver type. Such extensions can be called on an object variable even if its value is null, and can check for this == null inside the body. This is what allows you to call toString() in Kotlin without checking for null: the check happens inside the extension function.

fun Any?.toString(): String {
    if (this == null) return "null"
    // after the null check, 'this' is autocast to a non-null type, so the toString() below
    // resolves to the member function of the Any class
    return toString()
}
Spongy answered 24/1, 2018 at 18:42 Comment(0)
M
7

Be careful, for:

fun Any?.toString(): String

following behavior:

var obj: Any? = null

obj?.toString() // is actually null
obj.toString() // returns "null" string

just spent 15 very frustrating minutes before realized this...

Montes answered 2/7, 2020 at 14:33 Comment(0)
I
1

val string: String? = "Hello World!" print(string.length)
// Compile error: Can't directly access property of nullable type. print(string?.length)
// Will print the string's length, or "null" if the string is null.

?. Safe Call operator for nullable receiver##

The safe call operator returns null if the value to the left is null, otherwise continues to evaluate the expression to the right, so in order to call any function on nullable receiver you need to use safe call operator after Any.(Use Any?) Then you can check for null value of this(here this object points to receiver) inside function body.This is what allows you to call toString() in Kotlin without checking for null: the check happens inside the extension function.

fun Any?.toString(): String {
    if (this == null) return "null"
    // after the null check, 'this' is autocast to a non-null type, so the toString() below
    // resolves to the member function of the Any class
    return toString()
}
Iosep answered 3/2, 2020 at 8:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.