Swift Type Casting

Type Casting

  • is, as 명령어
  • Instance Type 확인
  • Class의 Instance를 Parent OR Child의 Type으로 사용할 수 있는지 확인
  • Up Casting, Down Casting

Furniture라는 Parent Class와 Furniture를 상속받는 Child Class인 Bed, Chair Class를 구현하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

class Furniture {
var yearOfProduction: Int

init(yearOfProduction: Int) {
self.yearOfProduction = yearOfProduction
}

func description() -> String {
return "\(self.yearOfProduction)"
}
}


class Bed: Furniture {
var size: String

init(yearOfProduction: Int, size: String) {
self.size = size
super.init(yearOfProduction: yearOfProduction)
}

override func description() -> String {
return "이 침대의 제작시기는 \(self.yearOfProduction)이고, 크기는 \(self.size) 입니다."
}
}


class Chair: Furniture {
var count: Int

init(yearOfProduction: Int, count: Int) {
self.count = count
super.init(yearOfProduction: yearOfProduction)
}

override func description() -> String {
return "이 의자의 제작시기는 \(self.yearOfProduction)이고, 남은의자의 개수는 \(self.count) 입니다."
}
}

Type Check

is, type(of: ) 명령어를 가지고 Type Check를 할 수 있다.

여기서 만든 wareHouse 배열은 Bed, Chair의 Parent Class인 Furniture Type으로 나타낸다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let wareHouse = [Bed(yearOfProduction: 2017, size: "King"), Bed(yearOfProduction: 2018, size: "Single"),
Chair(yearOfProduction: 2018, count: 4), Chair(yearOfProduction: 2016, count: 3), Chair(yearOfProduction: 2019, count: 6)]


print(type(of: wareHouse)) // Array<Furniture>
print(type(of: wareHouse[0])) // Bad
print(type(of: wareHouse[1])) // Bad
print(type(of: wareHouse[2])) // Chair
print(type(of: wareHouse[3])) // Chair
print(type(of: wareHouse[4])) // Chair


for item in wareHouse {
if item is Bed {
print("Bed Type")
} else if item is Chair {
print("Chair Type")
}
}

// Bed Type
// Bed Type
// Chair Type
// Chair Type
// Chair Type

Down Casting

Down Casting은 Child Class보다 더 상위에 있는 Parent Class의 Type을 Child Class의 Type으로 Casting하는 것을 나타낸다.

이때 Down Casting에 성공하면 부모의 Instance 저장 property만 사용가능하다.

왜냐면 원래 Parent Class가 Child Class의 타입으로 잠시 캐스팅하는 것일 뿐이다 즉 실제로 Instance를 수정하거나 값을 변경하는 작업이 아니기 때문이다.

tip: child as? parent 인 경우 즉 as? 앞이 child instance이고 as? 뒤가 Parent Type이면 Down Casting이 가능하다.

as? 조건부 다운 캐스팅 : 반환 Type이 Optional Type이며 실패시 nil이 반환된다.

as! 강제 다운 캐스팅 : 반환 Type이 일반 Type이며 실패시 런타임 오류가 발생한다.

  • 강제 다운 캐스팅은 실패시 런타임 오류가 발생하기 때문에 사용할 때 조심해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

let furniture: Furniture = Furniture(yearOfProduction: 2018)
let bed: Bed = Bed(yearOfProduction: 2016, size: "King")
let chair: Chair = Chair(yearOfProduction: 2017, count: 3)


print("\(bed.yearOfProduction), \(bed.size)") // 2016, King

if let downTest: Furniture = bed as? Furniture {
print(type(of: downTest))
print(downTest.yearOfProduction)
// print(downTest.size) // Value of type 'Furniture' has no member 'size'
} else {
print("fail")
}

// Bed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for item in wareHouse {
print(type(of: item))
if let bed = item as? Bed {
print(bed.description())
} else if let chair = item as? Chair {
print(chair.description())
}
}

//이 침대의 제작시기는 2017이고, 크기는 King 입니다.
//이 침대의 제작시기는 2018이고, 크기는 Single 입니다.
//이 의자의 제작시기는 2018이고, 남은의자의 개수는 4 입니다.
//이 의자의 제작시기는 2016이고, 남은의자의 개수는 3 입니다.
//이 의자의 제작시기는 2019이고, 남은의자의 개수는 6 입니다.

Share