kotlin-style-guide icon indicating copy to clipboard operation
kotlin-style-guide copied to clipboard

Using casts

Open yole opened this issue 9 years ago • 10 comments
trafficstars

Do not use free-standing as expressions for smart casts. Instead, assign a new name to the variable after the cast.

Good:

fun foo(x: Any) {
    val s = x as String
    s.length
}

Bad:

fun foo(x: Any) {
    x as String
    x.length
}

yole avatar May 31 '16 18:05 yole

Isn't the generated equals method doing what the second example does?

cypressious avatar May 31 '16 19:05 cypressious

I respectfully disagree.

If in the beginning of a function there is a cast x as String, it is basically an assertion to the function parameter. It describes the environment in which the function is used. Renaming of the parameter does not clarifies the change in type since x is always a String.

A similar situation:

fun foo(x: Any, y: Int?) {
    x as? String ?: return
    y ?: return

    x + y
}

voddan avatar Jun 08 '16 07:06 voddan

@voddan I personally find this syntax an abuse of smart casts. If this is really a common case (which I don't think it is), then we need to provide support for expressing this idea more cleanly.

yole avatar Jun 08 '16 07:06 yole

You can do if (x !is String) return but that's a bit more verbose.

cypressious avatar Jun 08 '16 07:06 cypressious

require(o is String) will not smart cast the value.

cypressious avatar Jun 08 '16 07:06 cypressious

@yole Could you please explain why x as String is less readable?

voddan avatar Jun 08 '16 07:06 voddan

It just doesn't look like an expression that does anything, which looks confusing. Yes, you can learn this pattern, and it is in fact concise, but it's just weird. (Also, as far as I understand, the fact that this works is an accident, and not an intention of the smart cast design.)

yole avatar Jun 08 '16 07:06 yole

Similarly, val s = x as String looks like something that may or may not happen, when in fact it acts as an assertion. I understand why you don't like x as String, but I don't see how the other option is better.

voddan avatar Jun 08 '16 07:06 voddan

@yole I'd consider this a happy accident in Language design and actually go ahead and add this pattern to https://kotlinlang.org/docs/reference/idioms.html as a recommended way to do type and nullability assertions (and checks with early returns) in function prologue code. Let it be idiomatic and it will not be confusing anymore.

elizarov avatar Nov 08 '16 10:11 elizarov

IMO this should be fixed in the language (and AFAIK it's going to) so that assert(x is String) would make a smart cast. Until that x as String is just a workaround.

valentinkip avatar May 29 '17 18:05 valentinkip