shle2821
shle2821

Reputation: 1886

In Swift, why have `as` operator. What does it benefit? Why did they put in?

I'm aware of what the as operator does and how to use them. But I'm more curious in the architectural side of the as operator. Why is it there? What's the huge reason? What does it help?

Example:

var objectData: NSData = NSUserDefaults.standardUserDefaults().objectForKey("myKey") as NSData

...wouldn't it be better if it's:

var objectData: NSData = NSUserDefaults.standardUserDefaults().objectForKey("myKey")

Upvotes: 0

Views: 191

Answers (3)

Airspeed Velocity
Airspeed Velocity

Reputation: 40965

You're right to be a bit confused, as prior to Swift 1.2, the as keyword was overloaded with multiple meanings. Swift 1.2 makes this a lot clearer, as there are now 3 versions of as: as, as? and as!. (in prior versions, as and as! where conflated as just as)

In your example (which I'm assuming is prior to 1.2 as otherwise it wouldn't compile), you are using as to do two things simultaneously.

NSUserDefaults.objectForKey's return type is an AnyObject?, an optional AnyObject. That is, it could be any kind of object, and it might not be an object at all (because there might not have been a value set for the key "myKey").

To make use of this result, you need to do two things – unwrap the optional (i.e. test if it contains a value), and convert the AnyObject to a more useful type (in this case, NSData).

Here's how you can do this:

if let objectData = NSUserDefaults.standardUserDefaults()
                      .objectForKey("myKey") as? NSData 
                   // note the question mark --^
{
    // use the value
}
else {
    // handle the value not being present – perhaps set it to a default value
}

This is using as? to test, tentatively, if the value returned by objectForKey is of type NSData. The if let tests if there was a valid value, and if it is of the correct type.

Bear in mind, there is a chance that the value stored for "myKey" is not compatible with the type you want. Suppose instead of an NSData you wanted an Int. You'd do if let intData = NSUserDefaults.standardUserDefaults().objectForKey("myKey") as? Int. If the value stored for "myKey" was the string "foo", this cannot be converted to an Int an you'd get an error.

If instead of using as? above, you use as, you force Swift to unwrap the value and convert the type without checking. If everything works out, that's fine. But if there was no value or if the data was not compatible with the type, you'll get a runtime assertion and your program will crash.

This is so dangerous that in Swift 1.2, this use of as has been renamed as!, the exclamation part indicating a dangerous "forcing" of the conversion. If you try to compile your example code in 1.2, you'll get an error asking if you meant as? or as!.

The as keyword remains for type clarifications that are always safe. For example, suppose you have an overloaded function like so:

func f(i: Int?)   { println("called with Int") }
func f(s: String) { println("called with String") }

// try to call f with nil – Swift will complain because it 
// doesn't know if this is a nil int or a nil string
f(nil)

// you can tell it which with as:
f(nil as Int?)    // prints "called with Int"
f(nil as String?) // prints "called with String"

There are also some kinds of Swift <-> Objective-C bridging conversions that are guaranteed to always succeed, which you can also use as for:

let a = [1,2,3]
// you can always convert a Swift array to an NSArray
let n = a as NSArray

Upvotes: 2

CouchDeveloper
CouchDeveloper

Reputation: 19116

First, we should know when to use it. Usually you use this operator in order to perform a "downcast" - that is, the operator tries to return an object reference as a derived class - and succeeds iff the object is actually of that kind. That implies, that the call-site has to make a guess about the actual kind of the object. This downcast can fail, too.

Thus, the answer is really twofold:

As OldPeculier already pointed out, "it's a well established paradigm and clearly useful".

However, there are other, better designs which could avoid a downcast which can potentially fail. Frequent use of a downcast is a code smell. You should strive to re-think your design, possibly using protocols, or class extensions and so force.

Upvotes: 0

Jeff Wofford
Jeff Wofford

Reputation: 11547

The benefit of as is that it confirms that the object on its left side is of the type on its right side. It differentiates between, for example:

myAnimalReallyADog as Dog

and

myAnimalReallyACat as Dog

Without it you would have to use other, probably more long-winded ways to test whether the object cast is legal.

The as concept is common among many languages and not unique to Swift, so it's a well-established paradigm and pretty clearly useful.

Upvotes: 1

Related Questions