Blog

[Swift] Type Casting

Published 2 min read

In most other languages, type casting is thought of as

'converting data types'

but Swift has one more thing.
In Swift, Type Casting has the following two meanings.

① Checking an instance's type … 2 ways
② Converting data types (upcasting, downcasting) … 3 ways

  1. Checking an instance's type
class Machine class IPhone: Machine class Galuxy: Machine

Say there are two classes Machine, IPhone, Galuxy,
and IPhone and Galuxy inherit from Machine.

Now say there are two variables.

var machine: machine = Machine() var iPhone_6: IPhone = IPhone() var galuxy_2s: Galuxy = Galuxy()

Then you can check types like this

1번 방식 print(machine is Machine) // True print(machine is IPhone) // False print(machine is Galuxy) // False print(iPhone_6 is Machine) // True print(iPhone_6 is IPhone) // True print(iPhone_6 is Galuxy) // Fasle 2번 방식 print(type(of: machine) == Machine.self) // True print(type(of: machine) == IPhone.self) // False print(type(of: machine) == Galuxy.self) // False print(type(of: iPhone_6) == Machine.self) // True print(type(of: iPhone_6) == IPhone.self) // True print(type(of: iPhone_6) == Galuxy.self) // Fasle
  1. Converting data types
var i: Int = 3 var f: Float = Float(i)

Looking at code like this, you might think you already know type casting,
but surprisingly, this code is neither data type conversion nor type casting.

It's the initializer of a struct named Float.
In other words, it didn't change the type, it made a new instance.

Also, for data type conversion you use three things: as, as!, as?.

(1) Upcasting

var machine: Machine = IPhone()

Upcasting is handled with as,
and it converts a child instance into a parent instance.
The machine variable stores the IPhone instance converted into a Machine instance.
And this is exactly the same as the code below.

var machine: Machine = IPhone() as Machine

The as Machine is omitted, and 'the compiler handles it for you.'

(2) Downcasting

The opposite of upcasting: a parent instance is converted into a child instance.
The compiler doesn't handle it automatically, so we need to know how to handle it.
Downcasting is handled withas!, as?.

! and ? carry the same meaning they had with optionals.
Casting with as! is what we usually think of:
when you do A as! B, just think of it as A being converted to B.
But if the conversion fails, an error occurs.

A as? B returns the result converted to an optional, so it can also check the type,
it leaves less room for developer mistakes, and you can handle nil with if let.

So, use as! the way you'd expect,
and use as? while handling the nil case with if let.

class Machine { var a = 1 var b = 2 } class IPhone: Machine { var c = 3 } var machine1: Machine = IPhone() var machine2 = Machine() if let iphone = machine1 as? IPhone { print(iphone.c) // printed } else { print("no no") } if let iphone = machine2 as? IPhone { print(iphone.c) } else { print("no no") // printed } print((machine1 as! IPhone).c) // prints successfully print((machine2 as! IPhone).c) // ERROR!

In machine1, the type is Machine, so you can't access the variable c.
But you end up needing to access c quite often. In that case, you have to cast it to IPhone.

But if the original object is Machine(), like machine2, nil is returned and no no is printed.

You can think about the last as! part with the same logic.

Comments

Leaving a comment stores your nickname (or GitHub profile info). Privacy policy

GitHub