class Animal { var name: String init(n: String) { name = n } }
class Human: Animal { func code() { print("Typing away...") } }
class Fish: Animal { func breathUnderWater() { print("Breathing under water.") } }
위와 같이 superclass와 subclass가 있을 때
let alex = Human(n: "Alex Kwon") let mallory = Human(n: "Mal O'Brien") let nemo = Fish(n: "Nemo")
let neighbor = [alex, mallory, nemo] let neighbor1 = neighbor[0]
let myDouble = 0.0 let myDoubleAsAnInt = Int(myDouble)
위의 코드는 double type인 'myDouble'을 'Int'를 이니셜라이징 함으로써 Int type으로 type casting을 한다. 하지만 이는 이니셜라이징을 했기 때문에 type casting이 아니다.
if neighbor[0] is Human { print("This is Human.") } // This is Human.
- 위와 같이 'is' keyword는 한 객체가 특정 data type을 가졌을 때 그 객체가 그 data type이 맞는지 확인할 수 있게 한다.
func findNemo(from animals: [Animal]){ for animal in animals { if animal is Fish { print(animal.name) } } } findNemo(neighbor) // Nemo
let somthing = superClassObject as! SubClass
아래의 코드는 'findNemo' 메서드에서 'animal'의 data type이 Fish인 것이 확인되어 Fish class가 가진 'breathUnderWater' 메서드를 실행하기 위한 과정이다.
func findNemo(from animals: [Animal]){ for animal in animals { if animal is Fish { let fish = animal as! Fish fish.breathUnderWater() } } } findNemo(neighbor) // Nemo // Breathing under water.
- 상수 fish에 할당 된 animal은 그 위에 if구문에서 data type을 확인한 animal이다. 여기에 'as!'를 통해 Fish class를 cast down해서 상수 'fish'는 Fish class가 된다.
if let fish = neighbor[1] as? Fish { fish.breathUnderWater() }else { print("Casting has failed.") } // Casting has failed.
- 'as?'는 'as?' 앞에 있는 object가 뒤에 있는 subclass를 inherit 할 수 있는지 불확실 할 때 사용한다. 그래서 상수 'fish'는 optional type이 된다. 그래서 위와 같이 optional binding이나 optional chaining을 해준다.
'as' keyword는 subclass Fish인 'fish'를 superClass 'Animal'로 되돌리는 역할을 한다.
let animalFish = fish as Aniaml
*'as'에 '!', '?'가 없는 이유는 subclass를 superclass로 올리는 과정이라 실패하는 경우가 없기 때문이다.