클래스의 상속과 재정의

쏘스야·2023년 4월 14일
0

ios 개발자의 첫걸음

목록 보기
53/61
/**
 클래스
 상속(Inheritance) 과 초기화(Initialization)
 
 */

 
// 1. 상속의 재정의


class Person {                  // 부모 클래스, super 클래스, 상위 클래스
    var id = 0
    var name = "이름"
    var email = "abc@gmail.com"
}


class Student: Person {         // 자식 클래스, Sub 클래스, 하위 클래스
    // id
    // name
    // email
    var studentId = 0
}

class Undergraduate: Student {
    // id
    // name
    // email
    //studentId
    
    var major = "전공"
}



/**
 클래스의 상속과 초기화
 1. 클래스의 상속
 - 상속은 유일하게 클래스에서만 지원하는 기능(구조체는 상속 불가능)
 - 본질적으로 성격이 비슷한 타입을 새로 만들 때
 */

class AClass {
    final var name = "이름"       // final 을 붙이면 해당 속성은 재정의가 불가능 의미
}

final class BClass: AClass {        // final 을 붙이면 더 이상 상속을 할 수 없음을 의미
    var id = 0
}

let b = BClass()
b.name


/*
 BClass 는 AClass를 상속해서 구현
 서브클래스는 슈퍼클래스로부터 멤버를 상속함
 
 클래스의 상속 금지의 키워드 final
 (경우에 따라서, 클래스의 상속을 금지해야하는 경우가 있음)
 
 (final 를 각 멤버 앞에 붙인 경우, 해당 멤버 재정의 불가라는 뜻)
 
 */


/**
 상위 클래스에서 존재하는 멤버를 변형하는 것을 재정의라고 함
 재정의를 하려는 멤버에는 override 키워드를 붙여야함 (자세한 내용은 다음 강의에서 다룰 예정)
 
 */


/**
 UIKit 의 상속 구조
 - 애플이 미리 만들어 놓은 UIKit 에서는 상속의 구조가 세밀하고 복잡하게 만들어져 있음
 - 상속의 구조를 외울 필요는 없고, 대량적인 내용만 이해하면 됨 ====> 프레임워크 강의에서 자세하게 설명 예정
 */


/**
 2. 재정의(Overriding)
 - 재정의
 - 서브클래스에서 슈퍼클래스의 동일한 멤버를 변형하여 구현
 
 - 재정의 가능한 대상(멤버)
 - 속성 (하지만, 저장 속성에 대한 재정의는 어떠한 경우에도 불가능)
 - 메서드 (메서드, 서브스크립트, 생성자)
 
  ==> 속성과 메서드는 재정의 방식이 다름
 
 */

class Aclass {                          // 부모 클래스
    func doSomething() {
        print("Do something")
    }
}

class Bclass: Aclass {                  // 자식 클래스
    override func doSomething() {       // 함수를 재정의 함.
        super.doSomething()             // 슈퍼클래스에 있는 메서드를 실행함.
        print("Do something. Do another job")
    }
}

var bclass = Bclass()
bclass.doSomething()

// Do something
// Do something. Do another job

// 메모리 관점으로 상속은 저장속성을 추가하는 개념 !!
// 메모리 관점으로 메서드는 새로운 주소를 추가하는 개념 !!

/**
 재정의 (Orverriding) 의 기본 문법
 */

class SomeSuperclass {
    
    var aValue = 0
    
    func doSomething() {
        print("Do something")
    }
}

class SomeSubclass: SomeSuperclass {
    
    // 저장속성의 재정의는 원칙적 불가
    // override var aValue = 3
    
    // 저장속성 ==> (재정의) 계산속성
    // 그러나, 메서드 형태로 부수적 추가는 가능
    override var aValue: Int {
        get {
            return super.aValue
        }
        set {       // salf 로 쓰면 안됨.
            super.aValue = newValue
        }
    }
    
    override func doSomething() {
        super.doSomething()
        print("Do something 2")
    }
}


var ssc = SomeSubclass()
ssc.aValue
ssc.aValue = 5
ssc.aValue

ssc.doSomething()



// 2-2. 재정의 예시
// 1. 속성의 재정의(엄격)


class Vehicle {
    var currentSpeed = 0.0
    
    var halfSpeed: Double {
        get {
            return currentSpeed / 2
        }
        set {
            currentSpeed = newValue * 2
        }
    }
}


class Bicycle: Vehicle {
    // 저장 속성 추가는 당연히 가능
    var hasBasket = false
    
    // 1. 저장속성 ===> 계산속성으로 재정의(메서드 추가) 가능
    override var currentSpeed: Double {
        // 상위 속성이기 때문에 super 키워드 필요
        get {
            return super.currentSpeed
        }
        set {
            super.currentSpeed = newValue
        }
    }
    
    // 2. 저장속성 ===> 속성감시자를 추가하는 재정의(메서드 추가는 가능)
//    override var currentSpeed: Double {
//
//        willSet {
//            print("값이 \(currentSpeed) 에서 \(newValue) 로 변경 예정")
//        }
//        didSet {
//            print("값이 \(oldValue) 에서 \(currentSpeed) 로 변경 예정")
//        }
//    }
    
    // 3. 계산속성을 재정의 가능 (super 키워드 주의)
//    override var halfSpeed: Double {
//        get {
//            return super.currentSpeed / 2
//        }
//        set {
//            super.currentSpeed = newValue * 2
//        }
//    }
    
    // 4. 계산속성을 재정의 하면서, 속성감시자 추가 가능 (속성감시자 부분 참고) - 예외적인 상황
//    override var halfSpeed: Double {
//        willSet {
//            print("값이 \(halfSpeed) 에서 \(newValue) 로 변경 예정")
//        }
//        didSet {
//            print("값이 \(oldValue) 에서 \(halfSpeed) 로 변경 예정")
//        }
//    }
    
}



// 2. 메서드의 재정의

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("자전거가 지나간다고 소리친다.")
//    }
    
    // 4. 서브스크립트도 재정의 가능
    override subscript(index: Int) -> String {
        get {
            if index > 4 {
                return "777"
            }
            return super[index]
        }
        set {
            super[index] = newValue
        }
    }
}

let v = Bicycle1()
v[6]
v.currentSpeed
v.makeNoise()
profile
개발자

0개의 댓글