The documentation for Kotlin is now located on the new site. This page is kept for historical reasons
Skip to end of metadata
Go to start of metadata
The documentation for Kotlin is now located on the new site. This page is kept for historical reasons

A type cast operator changes the static type of an expression after performing a run-time check.

Smart casts

In many cases, one does not need to use explicit cast operators in Kotlin, because the compiler tracks the is-checks for immutable values and inserts (safe) casts automatically when needed:

fun demo(x : Any) { 
  if (x is String) { 
    print(x.length) // x is automatically cast to String 
  } 
}

Automatic casts work for when expressions and while loops as well:

when (x) { 
  is Int -> print(x + 1) 
  is String -> print(x.length + 1) 
  is Array<Int> -> print(x.sum()) 
}

"Unsafe" cast operator

Usually, cast operator throws an exception if the cast is not possible. Thus, we call it unsafe. The unsafe cast in Kotlin is done by an infix operator as (see operator precedence):

val x : String = y as String

Note that null cannot be cast to String as this type is not nullable, i.e. if y is null, the code above throws an exception.
In order to match Java cast semantics we have to have nullable type at cast right hand side, like

val x : String? = y as String?

"Safe" (nullable) cast operator

To avoid an exception being thrown, one can use a "safe" cast operator as? that returns null on failure:

val x : String? = y as? String

Note that despite the fact that the right-hand side of as? is a non-null type String the result of the cast is nullable.

What's next

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jul 29, 2011

    Hi all. Kotlin Project looks very interesting. I wonder if you could comment on possibly extending your automatic typecasting for the following situation. As the ANTLR guy, I work with trees all time and they are often heterogeneous in that node types differ throughout the tree. Someone might pass me a subtree root and I need to access the children, but with specific types for which I need to do casting:

    There are number of ways around the cast, unfortunately I can't think of a way to do this without bending the static type rules. We could consider this as a case of automatic type inference. The declaration on the left is a very loud signal that has clear declared my intentions for the type. Compare this to simple x=y where the declaration of x is somewhere else. Static typing rules should be in full force in this case making that illegal. It's just too dangerous.

    Another way to look at it is automatic down casting. If we can guarantee that VarNode is a subclass of a generic node, perhaps it is legal We could restrict it to subclass interfaces. For example, given a variable of generic node type, Node n, perhaps we could allow n.resolveSymbol() where resolveSymbol is a method only found in the VarNode subclass of Node. It would be an error to call a random method not in a subclass or if the method name were ambiguous in the subclass hierarchy. This would let us avoid a dynamic method dispatch because you are statically guessing the type of n in the case of n.resolveSymbol().

    Anyway, it would be great to hear your thoughts on this. It seems like it gives you the flexibility of dynamic method dispatch, but with the speed of static methods. There would still be a dynamic cast check at runtime as there always is. Do you think it is worth  loosening the type system in this very specific case? It seems I spend most of my life doing downcasting.

    Regards,

    Terence

    1. Jul 30, 2011

      Hi Terence,

      First of all, it's great to hear from you!

      In Kotlin, you can omit type annotations on variables, so instead of leaving out the cast (that's what you request):

      val id : VarNode = a.getChild(0)

      You can say

      val id = a.getChild(0) as VarNode

      I.e. leave out the type annotation and keep the cast (as). Which is roughly the same number of characters, so there's little gain in relaxing the typing rules.

      You can also use pattern matching or extension functions, but this requires declaring the structure of your tree somewhere. And declaring the structure makes sense to me, because you already have a heterogenous tree anyway, why not have typed getters (or something like that) for children?

      1. Jul 30, 2011

        Hi! Great. :)  The as VarNode is a really good solution for the case above. Since I also do a lot of a.getChild(0).resolveSymbol(), I like your suggestion about typed getters. Java finally allows narrowing of return types for overridden methods, but it still is a very verbose and slow solution:

        For deeply nested hierarchies, you either have to walk up the super.getChild() chain at runtime (slow) or re-implement getChild() in every subclass (bad).

        Maybe a variation on generics; a predefined "this type" implicit parameter to a parameterized type. Random try:

        (Note: I'm a huge fan of generics for use with collections as List<Node> is excellent documentation and typecast reducer, but I don't think that they are worth the complexity in implementation and language semantics to allow user-defined generic classes. I have yet to see a really good example from my code or anybody else's that wasn't actually a collection-like thing. Perhaps I should expand my thoughts over in your generics area.  Removing wildcard types is a great idea you have.)

        1. Jul 30, 2011

          Hi Terence,

          in Java you could write:

          which would compile.

          But as you said, your nodes can have children of different type. Than maybe Effective Java, Item 29: Consider typesafe heterogeneous containers is a solution. With that pattern you could write:

          1. Jul 31, 2011

            Hi Alexander,

            Thanks for the response. Yep, it's those pesky different child types that really cause the trouble. The heterogeneous container solution you show is more flexible, but it is the same as a cast since I have to say VarNode. It would be really great to have some kind of flexibility or new type safe mechanism. What you think of the <This> implicit parameter thing I mentioned that sort of infers the surrounding class type and subclasses?

            1. Aug 01, 2011

              Hi Terence,

              as I understood your <This> example from above, it is covered by my first Java example:

              In it, the T parameter is used to carry the type of the special node itself which is VarNode. I don't know what the selfType does. But maybe you can use it instead of T in my example.

              But I don't see how a compiler could infer the type of heterogeneous children with static analysis. I like the is operator of Kotlin in combination with the when expression for this problem:

              val child = Node().children[0] 
              when(child) { 
                is VarNode => child.resolveSymbol() 
                is ExprRoot => child.doSomethingElse() 
              }

              @Andrey: Could you please tell me how the language for Kotlin is called in the code macro. Thanks.

              1. Jul 31, 2011

                Oh right! sorry. Yep, my <This> is covered.

                Yep, static analysis would not be able to say for sure whether or not n.resolveSymbol() is valid. So, technically, it would be a hole in the type system (one which a number of people have considered; I think the key word is "soft typing").  Without falling off the wagon into dynamic type land, however, a restricted version of dynamic typing might be worth the potential risk. The key would be the method invoked on the object. If the method exists in exactly one subclass, an automatic cast is inserted to that unique class. If it's ambiguous or does not exist in a subclass, its static type error. Although I've never used a language that allowed this, I think risk/reward equation would be in favor of allowing the specific softening. If I'm doing a typecast, it is always some kind of downcast related to heterogeneous data structures.

                1. Jul 31, 2011

                  Perhaps the solution is what you've done in Intellij 10: automatic cast insertion physically.  n.resolveSymbol() would become ((VarNode)n).resolveSymbol() automatically in the editor.  nice going, guys!  As long as I don't have to spell it out manually, it's cool I guess. :)

                  1. Jul 31, 2011

                    Terence: IDEA 10 knows always upfront what you are willing to type

                    1. Jul 31, 2011

                      IDEA is and has always been the best development environment for Java! :)

                2. Jul 31, 2011

                  Hi Terence,

                  I'm new to "soft typing". So I read Soft Typing. I see your point that a compiler could accept method calls on types where a subtype with this method exists. On the other hand it should reject all calls to methods where no such method exists on any subtype. With tool support one could mark such calls with soft type safety as warning. The IDE could than show up a hint which would transform the soft safe method call into an if (is ...) expression with the cursor in the else branch.

                  At the end I think, in a statically typed language, it should always obvious that a ClassCastException could occur at a given point in the source code.

                3. Aug 02, 2011

                  A problem with soft typing in Java is with dynamic linking:
                  at compile time there may be only one subclass that defined resolveSymbol(), but at runtime, potentially, there may be more classes loaded...

                  1. Aug 02, 2011

                    Wow! You're right. Forgot about that.  Ok, I'm convinced. No soft typing. Intellij will simply insert the cast for me upon ctrl-space :)

                4. Aug 02, 2011

                  BTW, Kotlin will probably have a This type you were talking about

              2. Aug 01, 2011

                > Could you please tell me how the language for Kotlin is called in the code macro.
                We've failed to parameterize original code macro so it's a different macro {jet}

  2. Aug 24, 2011

    The syntax for save v. unsafe casting with nulls is a bit too similar.  The concepts are good, I am happy that you considered them, but while casually reading code I'll have difficulty reading "String = x as String" v. "String? = x as String?" v. "String? = x as? String".  I see why you want to use the elvis operator as much as possible.  In this case I think it degrades readability.

    I cannot recall the attribution at the moment, but I am with the programmer who said he reads code far more often than he writes code. 

    1. Aug 24, 2011

      Agree on "we read more often than write"

      Disagree on the similarity argument: I think, the question mark jumps out boldly enough

  3. Sep 29, 2011

    Anonymous

    Any plan to expression tree?

    1. Sep 29, 2011

      If you mean the ability to get an AST for a Kotlin expression, then yes, we plan to have it like this:

      val a : Expression = [ast] (x + y)

      where [ast] is an annotation you can put on any expression

      1. Sep 29, 2011

        Anonymous

        Nice ! Thank you. So, something like linq is possible.

  4. Sep 12, 2013

    Why no smart casts for local vars?

    I have code similar to this fragment:

            var y = x
            if (y is Int) y*2

    However the compiler informs me: Kotlin: Automatic cast to 'jet.Int' is impossible, because 'y' could have changed since the is-check
    How can this be? How could y change since the is-check. I can understand it for member variables, but local variables? Am I missing something?

    1. Sep 12, 2013

      We are going to support this case, although in general smart casts with vars are not possible when loops are present.