swift-10 상속

영점·2022년 10월 5일
0

Swift_Study

목록 보기
10/12

스터디를 진행하며 처음부터 다시 Swift를 공부하고 있습니다.
오늘 작성할 파트는 상속 입니다.

정의

클래스는 다른 클래스에서 메서드, 프로퍼티, 그리고 다른 특성을 상속 (inherit)할 수 있다.
클래스가 다른 클래스로 부터 상속될 때 상속하는 클래스를 하위 클래스 (subclass)라고 하고
상속된 클래스를 상위 클래스 (superclass)라고 한다.

간단히 말하면 클래스를 상속받는 클래스는 자식 클래스고, 그 상속된 클래스는 부모 클래스이다.

자식클래스 = 서브클래스
부모클래스 = 슈퍼클래스

공식에 이렇게 나와있으니 당연한거지만 구조체는 상속이 불가능하다.
상속도 단일 상속만 가능.. ( 후에 배울 프로토콜처럼 : 뒤에 여러개를 놓을 수 없다. )

기본 클래스

앞서 클래스와 구조체에서 설명한 적이 있으니 간단하게 형태만..

class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
    func makeNoise() {
        // do nothing - an arbitrary vehicle doesn't necessarily make a noise
    }
}

let someVehicle = Vehicle() //-> 초기화 구문 으로 Vehicle 의 새로운 인스턴스를 생성

print("Vehicle: \(someVehicle.description)")
// Vehicle: traveling at 0.0 miles per hour

서브클래스, 슈퍼클래스

하위 클래스(Subclassing)는 기존 클래스를 기반으로 새로운 클래스를 만드는 작업이다.
하위 클래스는 기존 클래스의 특성을 상속하므로 수정할 수 있으며, 새로운 특성도 추가할 수 있다.

먼저 위의 Vehicle 클래스를 상속한 Bicycle 클래스를 선언한다.

여기서 Vehicle슈퍼클래스, Bicycle서브클래스라고 부른다.

class Bicycle: Vehicle {
    var hasBasket = false
}

새로운 Bicycle클래스는 위에 있는 Vehicle의 모든 특성을 자동적으로 얻는다.
추가로 이 자전거는 현재 바구니를 가지고 있지 않다. ( 새로운 저장 프로퍼티 hasBasket )

인스턴스가 생성된 후에 특정 Bicycle인스턴스의 hasBasket프로퍼티를 true로 설정할 수 있다.
또한 상속된 프로퍼티를 수정할 수 있고 조회할 수도 있다. ( currentSpeed와 description 프로퍼티 )

let bicycle = Bicycle()
bicycle.hasBasket = true

bicycle.currentSpeed = 15.0
print("Bicycle: \(bicycle.description)")
// Bicycle: traveling at 15.0 miles per hour

+) 하위 클래스는 그 자체로 하위 클래스화 될 수 있다. 그 클래스는 기존 클래스와 하위 클래스 프로퍼티를 모두 상속하게 되며, 또한 그 클래스에 새로운 프로퍼티를 추가할 수도 있다. 상속된 프로퍼티, 새로운 프로퍼티 모두 수정이 가능하고 조회도 가능하다.

상속 재정의 ( 오버라이딩 )

부모 클래스에서 상속받은 것을 자식 클래스에서 재정의할 수 있는 것을 말한다.

오버라이딩은 인스턴스 메소드, 타입 메소드, 인스턴스 프로퍼티, 타입 프로퍼티, 서브스크립트 모두에 대해
가능하며, 상속될 특성을 재정의 하려면 앞에 override 키워드를 붙여준다.

위의 정의를 간단하게 말하자면,
내가 기존에 클래스A를 선언했는데 클래스B클래스A를 상속한 상황이고, 이후에 클래스A에 선언한 프로퍼티의 값들을 클래스B에서 변경하고 싶을 때 상속 재정의를 사용한다.

메서드 오버라이딩

예제를 통해 상속 재정의에 대해 더 자세히 보자면

class Human {
    func comment() {
        print("my name is dtzero")
    }
}

이렇게 comment라는 메서드를 선언했는데

class Me : Human {
    func comment() {
        print("my name is dotzer0")
    }
}

이렇게 Human을 상속한 Me 클래스에서 값을 변경하려 한다면.. 이렇게 에러가 나게 된다.

Overriding declaration requires an 'override' keyword

해당 에러를 고치기 위해 override를 사용하면 내 슈퍼클래스인 Human의 comment 함수를
내 입맛에 맞춰서 재정의해서 쓰겠다는 의미가 된다.

그럼 출력할 때 변경된 값이 출력된다.

만약 변경 전과 변경 이후의 메세지 모두 출력하고 싶다면,
super 접두어를 사용하여 메서드, 프로퍼티, 또는 서브 스크립트의 상위 클래스 버전을 접근한다.

class Me : Human {
    override func comment() {
    	super.comment()
        print("my name is dotzer0")
    }
}

그리고 해당 값을 출력하면.. 변경 전과 후의 값이 모두 출력된다.

let prints: Me = .init()
prints.comment()

/*
my name is dtzero
my name is dotzer0
*/

프로퍼티 오버라이딩

프로퍼티에 고유한 사용자 정의 gettersetter를 제공하거나 기본 프로퍼티 값이 변경될 때 재정의한 프로퍼티가 관찰할 수 있도록 프로퍼티 관찰자를 추가 하기위해 상속된 인스턴스 또는 타입 프로퍼티를 재정의할 수 있다.
주의할 점은 프로퍼티 오버라이딩을 할 때 프로퍼티의 이름과 타입을 반드시 명시해야 한다는 것이다.

먼저 앞서 배웠던 프로퍼티에는 저장 / 연산 프로퍼티가 있었다.
저장 프로퍼티의 경우, 재정의를 할 때 gettersetter를 모두 구현해줘야 한다.
getter 하나만 구현하는 것도 불가능하고 구현하지 않고 재정의도 불가능하다.

class Human {
    var name : String = "dtzer0"
}

class Me : Human {
    var me : String = "dotzero"
    
    override var name: String {
        get {
            return self.me
        }
        set {
            self.me = name
        }
    }
}

출력해보면 변경된 값이 알맞게 들어가있는걸 확인할 수 있다.

var test1 : Human = .init()
print(test1.name)

var test2 : Me = .init()
print(test2.me)

/*
dtzer0
dotzero
*/

연산 프로퍼티의 경우, 부모 클래스의 연산 프로퍼티가 getter로만 구현된 경우 서브 클래스에서 getter만 구현하거나 setter 를 추가로 구현하는 오버라이딩은 가능하지만,
만약 부모 클래스에서 둘 다 구현했다면 서브 클래스에서 둘 다 구현해줘야한다.

해당 사항말고 나머지는 저장 프로퍼티랑 같다.

재정의 방지

final을 통해 실수로 메서드, 프로퍼티, 또는 서브 스크립트를 재정의 하는 것을 방지할 수 있다.
final을 class 앞에 붙이게 되면 해당 클래스는 아무도 상속할 수 없게 된다.

상속을 시도할 경우, final 클래스를 선언한걸 상속했다고 에러가 난다.

final class Human {
    var name: String?
    var age: Int?
}

class Me : Human {
	//Inheritance from a final class 'Human'
}
profile
일단 배운내용은 적어두기

0개의 댓글