ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • swift - Inheritance and Polymorphism #2 (Type Check Operator, Type Casting)
    swift 2021. 1. 12. 14:38


    class Figure {
       let name: String
       
       init(name: String) {
          self.name = name
       }
       
       func draw() {
          print("draw \(name)")
       }
    }
    
    class Triangle: Figure {
       override func draw() {
          super.draw()
          print("🔺")
       }
    }
    
    class Rectangle: Figure {
       var width = 0.0
       var height = 0.0
       
       override func draw() {
          super.draw()
          print("⬛️ \(width) x \(height)")
       }
    }
    
    class Square: Rectangle {
       
    }
    
    class Circle: Figure {
       var radius = 0.0
       
       override func draw() {
          super.draw()
          print("🔴")
       }
    }
    
    
    // 두 피연산자의 타입이 일치하면 true
    // 왼쪽 피연산자의 형식이 오른쪽 피연산자의 형식과 동일한 상속계층에 있고 오른쪽 피연산자의 형식이 슈퍼 클래스이면 true
    // 나머지는 false
    // type check는 run time에 실시된다.
    
    let num = 123
    
    num is Int // true
    num is Double // false
    
    let t = Triangle(name: "Triangle")
    let r = Rectangle(name: "Rect")
    let s = Square(name: "Square")
    let c = Circle(name: "Circle")
    
    r is Rectangle // true
    r is Figure // true
    r is Square
    
    
    // 왼쪽에 표현식 오른쪽에 형식
    // 왼쪽 피연산자의 형식이 오른족 형식과 호환된다면 오른쪽 형식으로 casting된 인스턴스를 return -> 새로운 인스턴스가 리턴되는게 아님
    // 이미 존재하는 인스턴스에서 오른쪽 피연산자의 형식의 멤버만 접근할 수 있는 임시 인스턴스를 리턴
    
    // 형식 3개가지
    // 1. compile time casting (bridging : 서로 호환되는 형식을 casting하는 것)
    
    // 예시
    // 구조체로 구현된 String 자료형은 클래스로 구현된 NSString 자료형과 호환된다.
    let nsstr = "str" as NSString
    // 캐스팅 실패시 compile err
    // "str" as Int
    
    // 2. runtime Cast
    // 2-1. Conditional Cast
    // ?가 붙어있는 경우
    // casting에 성공하면 캐스팅된 인스턴스를 리턴하고 실패하면 nil리턴
    t as? Triangle
    t as! Triangle
    // 2-2. forced casting
    // 캐스팅에 실패하면 crush 발생
    
    var upcasted: Figure = s
    // compile time casting으로 upcasting
    upcasted = s as Figure
    
    upcasted as? Square
    upcasted as! Square
    upcasted as? Rectangle
    upcasted as! Rectangle
    
    upcasted as? Circle // nil
    // upcasted as! Circle // crush
    
    
    // 실제로 donwcasting을 구현할 때는
    // conditional과 optional을 같이 사용하는게 좋다.
    if let c = upcasted as? Circle {
        
    }
    // 배열에는 동일한 형식만 저장할 수 있는데 요기서 보면 에러없이 잘 생성됨
    // 모든 요소가 동일한 상속계층에 있다면 가장 근접한 슈퍼 클래스로 upcasting되서 들어간다.
    let list = [t, r, s , c]
    
    for item in list {
        // 현재 list안의 요소들은 Figure로 upcasting된 상태지만
        // 실행시켜보면 각각 다른 draw 결과물이 실행된다.
        // 이것을 polymorphism, 다형성이라고 한다.
        item.draw()
        // Figure에 선언된 멤버변수에만 접근할 수 있다.
        // 그럼 radius속성에 접근하는 방법은? -> downcasting
        // item.radius
        
        if let c = item as? Circle {
            print(c.radius)
        }
    }

    댓글

Designed by Tistory.