Swift’s var is not Objective-C’s id

Screenshot 2014-07-23 16.28.13

I saw a YouTube video a little while back that said “var in Swift is basically the same as id in Objective-C.” And honestly, when I first heard that statement, I thought, “yeah, var is like id in Objective-C. You just use it before a variable’s name when you don’t care about its type.” But that’s totally wrong, and I’ll explain why. Let me repeat that: Swift’s var is not at all the same as Objective-C’s id.

For example, in Objective-C, we can do this:

id number = @42;

And in Swift, we can do this:

var number = 42

So in both cases, we’re leaving off the type declaration: no NSNumber in Objective-C, and no Int in Swift. So var and id are the same, right? NOPE. Despite this similarity, var is not at all like id – and that’s because Swift is not Objective-C. Let’s look at how they’re different.

Swift is a statically typed language, so once a variable (var) is defined, the type of that variable will remain the same forever. With id in Objective-C, that’s not necessarily the case. For example, this is perfectly valid Objective-C code:

id x = @1;
x = @"hello";

And to show how Swift differs, here’s an approximation of the above in Swift. (I’d encourage you to create a new playground in Xcode and follow along. It’ll sink in more if you’re typing out the code.)

var x = 1
x = "hello"

You’ll see that the Swift above fails to compile. In Swift, once a variable is defined, you can’t change its type. And this, as we saw, is not the case in Objective-C, where we changed the type of x from NSNumber to NSString.

This illustrates the difference between Swift and Objective-C, or in a more general sense, the difference between statically typed and dynamically typed languages.

Let’s look at the definition of those words: “static” and “dynamic”. Starting with “static”, courtesy of the Dictionary in OS X:

“lacking in movement, action, or change”

So if calling something static means that it lacks movement, action, or change, then saying a language is statically typed means that its types cannot change. And that’s what we have in Swift.

Contrast this with “dynamic”:

“characterized by constant change, activity, or progress”

Sounds a bit like Objective-C’s id type, right? Its type is contantly changing, or at least, it can be changed constantly, as we did in the example above.

“But wait,” you may be thinking, “Swift’s var is constantly changing, too – it’s just like Objective-C’s id.” And you’re half-right – we can do the following in Swift:

var a = 1
var b = "hello"

So it looks like var is constantly changing – sometimes it represents an Int, sometimes a String. But the type of the variable never changes – our a is always an Int, and our b is always a String. And remember our previous example, where we tried to change x from 1 to “hello” and the compiler screamed at us. Once a variable’s type is set in Swift, it’s set. It can’t change. And that’s what static typing is.

So that brings us to another question: how is a variable’s type set in Swift? Let’s look at our previous Swift example again:

var x = 1
x = "hello"

The error from the compiler (on line 2 above) gives us the type. The error says (in Xcode 6 Beta 4):

Type ‘Int’ does not conform to protocol ‘StringLiteralConvertible’

So we can conclude that Swift has inferred the type of x – it’s an Int, and we didn’t call it one. This is known as type inference, and it’s one nice feature in Swift that’s not in Objective-C.

Let’s look at the definition of the word “infer”:

“deduce or conclude (information) from evidence and reasoning rather than from explicit statements”

Swift uses type inference to conclude that our little x is of type Int, even though we didn’t explicitly state that x should be an Int. And then it prevents us from changing x to a String since Swift is statically typed. This is in stark contrast to Objcetive-C, which requires explicit types and is dynamically typed.

In conclusion

Swift’s var is decidedly not Objective-C’s id – it’s just a keyword we use to state that we’re creating a variable. That variable’s type is inferred by the compiler via a feature called type inference, and once that variable has a type, it always has that type. Once an Int, always an Int.

If you enjoyed this…

..and you want to learn more Swift, enter your name and email below to get the 5-Part Guide to Getting Started with Swift.

You might also like these other hand-picked articles on Swift…

Swift: Strings aren’t objects

Working with Generics in Swift

How to write unit tests in Swift with XCTest