[Swift 문법] 상속

!·2022년 8월 25일
0

Swift 문법

목록 보기
25/27

상속

  • 다른 타입들과 구분되는 클래스의 특징이 상속 을 지원한다는 것이다.
  • 다른 프로그래밍 언어와 마찬가지로 메서드뿐만 아니라, 프로퍼티, 서브스크립트도 재정의(오버라이드) 할 수 있다.
  • 연산 프로퍼티를 정읳준 클래스에서는 프로퍼티 감시자를 구현할 수 없지만, 부모클래스에서 연산 프로퍼티로 정의한 프로퍼티든 저장 프로퍼티로 정의한 프로퍼티든 자식클래스에서는 프로퍼티 감시자를 구현할 수 있다.

클래스 상속

class 클래스이름: 부모 클레스 이름{
	프로퍼티와 메서드들
}
  • 상속받은 클래스는 부모클래스의 모든 특성들을 물려받는다.
  • 서브스크립트, 프로퍼티, 인스턴스프로퍼티, 타입 프로퍼티 등등...

재정의(오버라이드)

  • 자식클래스는 부모클래스에서 물려받은 특성들을 자신에 맞게 재정의 할 수 있다.
  • 만약 자식클래스에서 재정의 하였지만, 부모클래스의 특성으로 접근하고자 할때는 super 키워드를 사용하면 된다.
super.someMethod()
super.someProperty
super[index]

프로퍼티 재정의

  • 메서드와 마찬가지로 부모클래스로부터 상속받은 인스턴스 프로퍼티나 타입 프로퍼티를 자식클래스에서 용도에 맞게 재정의할 수 있다.
  • 프로퍼티를 재정의한다는 것은 프로퍼티 자체가 아닌 프로퍼티 접근자, 설정자, 감시자 등을 재정의 하는 것을 의미한다.
  • 부모클래스에서 읽기 전용 프로퍼티였더라도 자식클래스에서 읽고 쓰기가 가능한 프로퍼티로 재정의해줄 수 있다.
  • 그러나, 읽기 쓰기가 모드 가능한 프로퍼티를 읽기 전용으로 재정의 할 수 없다.

프로퍼티 감시자 재정의

  • 읽기 전용 프로퍼티나, 상수 저장 프로퍼티는 감시자를 재정의 할 수 없다. 왜냐하면 읽기 전용 프로퍼티와 상수 저장 프로퍼티는 값의 변경이 불가능하기 때문이다.
  • 또한, 프로퍼티 접근자와 프로퍼티 감시자는 동시에 재정의 할 수 없다.

상속 - 이니셜라이저

클래스의 이니셜라이저는 2가지있다. 지정 이니셜라이저편의 이니셜라이저 이다.
지정 이니셜라이저의 경우에는 프로퍼티를 초기화하는 이니셜라이저를 의미하고, 편의 이니셜라이저는 편의를 위한 이니셜라이저로써 반드시 내부에서 지정이니셜라이저를 호출해야한다.

  • 지정 이니셜라이저
init(매개변수){
	초기화코드
}
  • 편의 이니셜라이저
convenience init(매개변수){
	초기화 코드 및 지정 이니셜라이저 호출
}

클래스의 초기화 위임

지정 이니셜라이저와 편의 이니셜라이저간의 관계를 정리하기 위해 세 가지 규칙을 적용할 수 있다.

  • 자식클래스의 지정이니셜라이저는 부모클래스의 지정이니셜라이저를 반드시 호출해야한다.
  • 편의이니셜라이저는 자신을 정의한 클래스 내부의 지정이니셜라이저를 반드시 호출해야햔다.
  • 편의이니셜라이저는 궁극적으로 반드시 지정이니셜라이저를 호출해야한다.

2단계 초기화

스위프트의 컴파일러 는 프로퍼티의 초기화를 오류없이 진행하기위해 2단계 초기화(저장 프로퍼티 초기값 할당 -> 저장 프로퍼티 사용자 정의)를 거치며, 그를 위헤 4가지의 안전 확인을 실행한다.

  • 자식클래스의 지정 이니셜라이저가 부모클래스의 이니셜라이저를 호출하기위해 자신의 프로퍼티를 모두 초기화했는지 확인한다.
  • 자식클래스의 지정 이니셜라이저는 상속받은 프로퍼티에 값을 할당하기 전에 반드시 부모클래스의 이니셜라이저를 호출해야한다.
  • 편의 이니셜라이저는 자신의 클래스에 정의한 프로퍼티에 값을 할당하기 이전에 반드시 지정 이니셜라이저를 호출해야한다.
  • 초기화 1단계를 마치기 전까지는 이니셜라이저는 인스턴스 메소드를 호출할 수 없으며, 또 인스턴스 프로퍼티의 값을 읽어드릴 수도 없습니다. self 프로퍼티를 자신의 인스턴스를 나타내는 값으로 활용할 수도 없습니다.

이니셜라이저 상속

기본적으로 스위프트의 이니셜라이저는 부모클래스의 이니셜라이저를 상속받지 않는다. 만약 부모클래스의 이니셜라이저와 동일한 이니셜라이저를 사용하고자 한다면, 재정의를 통해 이니셜라이저를 구현해주어야한다. 이때 override 키워드를 통해 재정의 해주면 된다. 만약, 자식클래스의 편의 이니셜라이저가 부모클래스의 지정이니셜라이저를 재정의한다면 override 를 붙이면 되지만, 부모클래스의 편의 이니셜라이저를 자식클래스에서 재정의하고자 한다면 override 를 붙힐 필요가 없다. 왜냐하면 어차피 호출할 수 없기때문이다. 또한, 실패 가능한 이니셜라이저를 실패 가능하지 않은 이니셜라이저로 재정의할때도 override 키워드를 붙이면 되며, 반대의 경우도 마찬가지이다.


이니셜라이저 자동 상속

기본적으로 스위프트는 이니셜라이저가 자동으로 상속되지는 않지만, 특정 조건이 만족된 경우 부모클래스의 이니셜라이저가 자동으로 상속된다.
자식클래스에서 프로퍼티에 기본값을 모두 재공한다고 가정할 때 , 특정 조건은 2가지이다.
1. 자식클랫스에서 별도 지정 이니셜라이저를 제공하지 않는다면, 부모 클래스의 지정 이니셜라이저가 자동으로 상속된다.
2. 만약 조건1이에 따라 부모클래스의 지정 이니셜라이저를 모두 상속받은 경우, 부모클래스의 지정 이니셜라이저를 모두 재정의 하여 사용할 수 있다면 부모클래스의 편의 이니셜라이저가 자동으로 상속된다.

class Person{
	let name: String 
    
    init(name: String){
    	self.name = name
    }
	
    convenience init(){
    	self.init(name: "Unknown")
    }
}

class Student: Person{
	var major: String = "swift"
}

Student 클래스의 major 프로퍼티에 기본값이 있으므로, 부모 클래스의 지정 이니셜라이저 및 편의 이니셜라이저가 자동으로 상속된다.

class Person{
	let name: String 
    
    init(name: String){
    	self.name = name
    }
	
    convenience init(){
    	self.init(name: "Unknown")
    }
}

class Student: Person{
	var major: String
    
    override init(){
    	self.major = "Unknown"
        super.init(name: name)
    }
    
    init(name: String, major: String)}
    	self.major = major
        super.init(name: name)
    }
}

Student 클래스의 새로운 지정 이니셜라이저가 구현되어 있지만, 부모 클래스의 지정 이니셜라이저들이 모두 재정의가 되어 있어 사용할 수 있기때문에 부모클래스의 편의 이니셜라이저가 자동 상속되어 있다. 또한 자식클래스에서 편의 이니셜라이저를 새로 구현해도 상속받는 편의 이니셜라이저는 영향받지 않는다.


요구 이니셜라이저

required 수식어를 이니셜라이저 앞에 명시해주면 이 클래스를 상속받은 자식클래스는 반드시 해당 이니셜라이저를 재정의 해야한다.

class Person{
	var name: String
    
    required init(){
    	self.name = "unknown"
    }
}
class Student: Person{
	var major: String = "unknown"
}

Person 클래스에 요구 이니셜라이저를 구현하였지만, 이를 상속받은 Student 클래스에서는 요구 이니셜라이저를 구현하지 않았다. 왜냐하면, 요구 이니셜라이저가 자동 상속되었기 때문이다.
만약 Student 클래스에 새로운 지정 이니셜라이저를 구현한다면, 요구 이니셜라이저 또한 마찬가지로 재정의 해야한다.

만약 부모 클래스에 일반 이니셜라이저를 자식 클래스에서 요구 이니셜라이저로 재구성할 수 있다. 이때는 required ovderride 키워드를 명시하면되며, 편의 이니셜라이저 또한 요구 이니셜라이저로 재정의 할 수 있다. 이 때 키워드는 required convenience 키워드를 명시하면 된다.

profile
개발자 지망생

0개의 댓글