Downcasting using as! and as? in Swift

How to use as! and as? for downcasting and what are the differences between them

What is Downcasting ?



Behind the scenes a variable or constant of a class type may be a subclass of another class type.

For example a variable of type Any may be referring to a String.

Here is another example of class Pet

class Pet {
    
    var name: String
 
    init(name: String) {
        self.name = name
    }
}

Then we define two subclasses of Pet

class Dog: Pet {
    
    var breed: String
    
    init(name: String, breed: String) {
        
        self.breed = breed
        super.init(name: name)
    }
}

class Cat: Pet {
    
    var color: String
    
    init(name: String, color: String) {
        
        self.color = color
        super.init(name: name)
    }
}

Finally we will create an array that contains one dog and two cats

let pets = [Dog(name: "Thor", breed: "Bulldog"),
            Cat(name: "Sophia", color: "Yellow"),
            Cat(name: "Tigress", color: "Black")]

The Swift type checker knows that Dog and Cat classes have a common subclass of Pet so the Pets array is inferred to be [Pet]

If you iterate over the pets array the items you get back are of type Pet but behind the scenes they are still Dog and Cat types

To use them as Dog and Cat you need to Downcast them using as! or as?

Using as! and as? to downcast

as? is a conditional cast operator and it always returns an optional so if the downcast failed you will get nil

as! is a forced cast operator so if the downcasting failed you will get a runtime error, this is why you must be sure that the downcast will succeed if you decided to use as!

Back to our example lets use as? to cast the items of our pets array

for pet in pets {
         if let dog = pet as? Dog {
            print("a dog named \(dog.name) and breed \(dog.breed)")
         }
         else if let cat = pet as? Cat {
            print("a cat named \(cat.name) and color \(cat.color)")
         }
}

this is the result

a dog named Thor and breed Bulldog
a cat named Sandy and color Yellow
a cat named Tigress and color Black

Note that we have used the conditional downcast operator as? because we are not sure which item is Dog and which one is Cat but if for example we are sure that all items are of Dog class type then we could use the forced downcast operator as!

Leave a Reply

Your email address will not be published. Required fields are marked *