Search code examples
kotlinkotlin-null-safety

Kotlin: Cannot apply two conditionals at once check with "return body" function style


I have a simply function check like this:

    fun parseValidBluetoothBrickedId(controllerId: String?): Boolean{
    if(controllerId != null){
        if(controllerId.startsWith(BLUETOOTH_NAME_PREFIX) && controllerId.length > BLUETOOTH_NAME_PREFIX.length)
            return true
    }

    return false
}

I want to convert it to simplier style:

   fun parseValidBluetoothBrickedId(controllerId: String?) =
        controllerId?.length > BLUETOOTH_NAME_PREFIX.length
      &&  controllerId?.startsWith(BLUETOOTH_NAME_PREFIX)

but IDE(Android Studio 3.0 Beta7) gives me an error, underlines the greater than('>') operator:

Operator calls corresponds to a dot-qualified call 'controllerId?.length.compareTo(BLUETOOTH_NAME_PREFIX.length) which is not allowed here

Also it underline as an error line controllerId?.startsWith(BLUETOOTH_NAME_PREFIX) and says:

Type mismatch. Required: Boolean, Found Boolean?

What is the problem, really? It is just a simply method, works well with the first block if-else style.


Solution

  • You can't call compareTo (use the < operator) on controllerId?.length, since its type is Int?, which means it might be null, in which case it can't be compared as a number.

    Similarly, the controllerId?.startsWith(BLUETOOTH_NAME_PREFIX) call returns Boolean? (since it will return null if controllerId is null), which can't be passed to the the && operator, only a real Boolean can.

    The solution here is to do the null check that you were doing in your original method, and get rid of the safe calls by relying on smart casts casting your controllerId to String:

    fun parseValidBluetoothBrickedId(controllerId: String?): Boolean =
            controllerId != null 
            &&  controllerId.length > BLUETOOTH_NAME_PREFIX.length
            &&  controllerId.startsWith(BLUETOOTH_NAME_PREFIX)