Casting

There will be times when you want to convert from one type to another. For this, we use a process called "type casting", which uses the keyword as: object as(?/!) type. If object is of type type or is a subtype of type type then there will be a successful casting to type. This also works for protocols if you want to encapsulate features. For types that are guaranteed to be able to convert, we can use the direct as. This works for anything that is already declared to be the casting type:

let x = 3
// x: Int = 3
let y = x as Int

Or for objects that are declared to be subclasses to the casting type or a conformant of the conforming type.

class aClass {}
class aSubClass: aClass {}

let myObject = aSubClass() as aClass
// myObject: aClass = aSubClass()

protocol aProtocol {}
class aConformant: aProtocol {}

let myProtocolConformant = aConformant() as aProtocol
// myProtocolConformant: aProtocol = aConformant()

Casting Down

As you can imagine, this process gets a little more complicated when we can't guarantee successful casting. This happens when we are casting from superclass to subclass or unrelated types. In these cases, the casting will be optional–i.e. if the casting fails, it will return nil. As with every other optional type we have dealt with before, we need to handle the optional. We can either leave it as an optional with as? or we can force unwrap it with as!.

class aClass {}
class aSubClass: aClass {}

let myEncapsulatedObject: aClass = aSubClass()
// myEncapsulatedObject: aClass = aSubClass()
let myObject = myEncapsulatedObject as? aSubClass
// myObject: aSubClass = aSubClass()

let undeclaredType: Any = 3
// undeclaredType: Any = 3
let myInt = undeclaredType as! Int
// myInt: Int = 3

let myFailingCast = undeclaredType as! String
// Could not cast value of type Int to String

Note: When casting to a protocol, if you do not explicitly conform to the protocol in your code, the cast will fail! No duck typing allowed!

Last updated