Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 284
K.Os Avatar asked Oct 09 '17 08:10

K.Os


2 Answers

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)
like image 79
zsmb13 Avatar answered Nov 16 '22 08:11

zsmb13


When you do controllerId?.length, you are getting an Int?. You cannot compare Int with an Int?. That is the reason you get the first error.

You get the other error because controllerId?.startsWith(BLUETOOTH_NAME_PREFIX) returns Boolean?. You cannot use the && operator on a nullable parameter. It requires two parameters of type Boolean.

To solve the problems, you need to check controllerId != null first. This will smart cast controllerId to the non-nullable type String. Like this:

fun parseValidBluetoothBrickedId(controllerId: String?): Boolean =
    controllerId != null
        && controllerId.startsWith(BLUETOOTH_NAME_PREFIX)
        && controllerId.length > BLUETOOTH_NAME_PREFIX.length
like image 2
marstran Avatar answered Nov 16 '22 07:11

marstran