Search code examples
swiftoperatorsdowncast

What use does the new as! operator have?


I don't quite understand what new functionality the as! operator is supposed to add.
Apple's documentation says:

The as! operator performs a forced cast of the expression to the specified type. The as! operator returns a value of the specified type, not an optional type. If the cast fails, a runtime error is raised. The behavior of x as! T is the same as the behavior of (x as? T)!.

It seems that using as! only makes sense, when you know that the downcast will be successful, because otherwise a runtime error will be triggered. But when I know that the downcast will be successful I just use the as operator. And since neither as! nor as return an optional they even return the exact same type.
Maybe I'm missing something, but what's the point?


Solution

  • The as (no bang) operator is for casts that are guaranteed by the language to succeed — primarily, that means casts from a subtype to one of its ancestor types.

    The as! and as? operators are for casts that the language can't guarantee will succeed. This comes into play when you have a general type and want to treat it as a more specific subtype. The compiler doesn't know which subtype might really be hiding behind the general type — that information can be decided at run time — so as far as the language knows, there's a possibility of the cast failing.

    The difference between as? and as! is how that failure is handled. With the former, the result of the cast gets wrapped in an optional, forcing you to yeast for the failure and allowing you to handle it in a way that makes sense to your app. The latter assumes the cast will succeed, so you aren't forced to check for failure—you'll just crash if your assumption turns out to be wrong.

    So why use as!? It fills the same role as the Implicitly Unwrapped Optional: you can use it (at your own risk) for situations where some behavior is "guaranteed" by some factor external to the language (even if the language itself can't guarantee it), allowing you to skip having to write code to test for failures you don't expect to happen. One of the most common cases of such is when you're depending on the runtime behavior of another class — the language doesn't say that the subviews array of a UIView must contain other UIViews, but its documentation assures you that it will.

    Before Swift 1.2, there was no as!as included both cases that could crash and cases that couldn't. The new operator requires you to be clear about whether you're doing something that will always succeed, something you expect to always succeed, and something you plan to test for failure.