[Swift] Inheritance


Inheritance


상속은 일단 추가적으로 필요한 데이터(저장 속성)을 늘린다는 관점에서 생각

class Person {
    var id = 0
    var name = "이름"
    var email = "abc@gmail.com"
}

// Person 클래스를 상속받음
class Student: Person {
    // id
    // name
    // email
    var studentId = 0
}

// Person 클래스를 상속 받은 Student 클래스를 상속받음
class Undergraduate: Student {  
    // id
    // name
    // email
    // studentId
    var major = "전공"
}
  • 기본 클래스 : 다른 어떤 것도 상속하지 않은 클래스
    • (상대적으로) 상속 하는 클래스 : 부모 클래스, 슈퍼 클래스, 상위 클래스
    • (상대적으로) 상속 받는 클래스 : 자식 클래스, 서브 클래스, 하위 클래스
  • 클래스의 상속 금지의 키워드 final
    • 경우에 따라서, 클래스의 상속을 금지해야하는 경우가 있음
    • final을 각 멤버 앞에 붙인 경우, 해당 멤버 재정의 불가라는 뜻
  • 수직 확장 : 본질적으로 성격이 비슷한 타입을 새로 만들어서
    • 데이터(저장 속성)를 추가하거나
    • 기능(메서드)을 변형시켜 사용하려는 것
  • 언어마다 다른데 스위프트는 다중상속을 지원 안함 (파이썬은 지원)

클래스 상속

class Aclass {
    func doSomething() {
        print("Do something")
    }
}

class Bclass: Aclass {
    override func doSomething() {  // 서브 클래스에서 슈퍼 클래스 함수 재정의
        super.doSomething()  // 서브 클래스에서 슈퍼 클래스의 메서드 호출
        print("Do another job")
    }
}
  • 오버라이딩(overriding, 재정의)
    • 클래스의 상속에서 상위클래스의 속성/메서드를 재정의(기능을 약간 변형해서) 사용하는 것
  • 재정의 가능한 대상(멤버)
    • 속성 (하지만, 저장 속성에 대한 재정의는 어떠한 경우에도 불가능)
    • 메서드 (메서드, 서브스크립트, 생성자)
      -> 속성과 메서드는 재정의 방식이 다름
  • 저장 속성의 재정의는 원칙적 불가 (데이터 구조의 변형은 불가)
    • 서브 클래스에서는 슈퍼 클래스의 속성들의 주소를 가르키기만 하기 때문

오버로딩(overloading, 과적)
함수에서 함수의 하나의 이름에 여러 함수를 대응시켜서 사용

클래스 재정의

// 상위 클래스
class Vehicle1 {
    var currentSpeed = 0.0
    
    var datas = ["1", "2", "3", "4", "5"]
    
    func makeNoise() {
        print("경적을 울린다.")
    }
    
    subscript(index: Int) -> String {
        get {
            if index > 4 {
                return "0"
            }
            return datas[index]
        }
        set {
            datas[index] = newValue
        }
    }
}

// 메서드의 재정의 방식
class Bicycle1: Vehicle1 {
    
    // 1) 상위 => 하위 호출 가능
    override func makeNoise() {
        super.makeNoise()
        print("자전거가 지나간다고 소리친다.")
    }
    
    // 2) 하위 => 상위 호출 가능
    override func makeNoise() {
        print("자전거가 지나간다고 소리친다.")
        super.makeNoise()
    }
    
    // 3) 상위구현 아예 무시 가능
    override func makeNoise() {
        print("경적을 울리고, 자전거가 지나간다고 소리친다.")
    }
    
    // 서브스크립트도 재정의 가능
    override subscript(index: Int) -> String {
        get {
            if index > 4 {
                return "777"
            }
            return super[index]
        }
        set {
            super[index] = newValue
        }
    }
}
  • 저장 속성 재정의 불가
    • 저장 속성은 실제 인스턴스에 각각의 멤버별(속성별로) 저장공간이 있고, 변형하는 것이 불가 (상속의 기본 원칙)
  • 메서드는 재정의 가능 (기능 확장만 가능, 기능 축소 불가)
    (재정의를 하지 않아도, 상속에서는 당연히 모든 멤버의 상속이 일어남)
    • 메서드는 타입(데이터 영역)에만 배열형태로 주소값을 저장되어 존재하므로 각 상속단계에서 재정의 되고 대체 되는 것이 당연
  1. 저장 속성
    • 재정의 불가
      • 메모리 구조에서 상위 구현을 참조하기 때문에 재정의(변형) 불가능
    • 예외) 메서드 형태로 부수적 추가는 가능
      (메모리 구조를 건드리지 않는 형태로는 가능)
      • 읽기 / 쓰기 계산속성 형태로 재정의 가능
        (메서드 추가 형태로 구현)
      • 속성 감시자 형태로 재정의 가능
        (실질적 단순 메서드 추가)
  2. 계산 속성
    • 계산 속성의 재정의는 실질적 메서드 대체
    • 확장 방식의 재정의 가능
      • 읽기 -> 읽기/쓰기 가능 (기능 확장 가능)
      • 읽기/쓰기 -> 읽기 불가능 (기능 축소 불가능)
    • 속성 감시자를 추가하는 재정의 가능 (실질적 단순 메서드 추가)
  3. 생성자
    • 생성자는 기본적으로 상속되지 않고 재정의 원칙
      (생성자는 모든 저장 속성을 초기화하는 도구이기 때문에, 서브클래스에 최적화 안되어 있음)
    • 상위 지정 생성자현재 단계의 저장 속성을 고려해서 구현
    • 예외) 생성자의 자동 상속
      • 지정 생성자 / 편의 생성자 자동 상속의 경우 있음
  4. 메서드
    • 일반적으로 상위구현의 메서드를 대체 및 변형 할 수도 있으므로, 자유롭게 재정의 가능
      (상위 구현을 호출하는 경우도 많으니 주의)

참고

Ellen Swift Class






© 2021. by hminkim