Hi yoahn 개발블로그

[Swift] #5 다양한 표현 및 확장 3 (상속 / 인스턴스 생성 / 소멸) 본문

프로그래밍 언어/swift

[Swift] #5 다양한 표현 및 확장 3 (상속 / 인스턴스 생성 / 소멸)

hi._.0seon 2021. 1. 20. 22:45
반응형

1. 상속

  • 상속은 클래스, 프로토콜 등에서 가능합니다.
  • 열거형, 구조체는 상속이 불가능합니다.
  • 스위프트의 클래스는 단일상속으로, 다중상속을 지원하지 않습니다.
  • 생성자는 자동 상속이 되지 않는다.
class 이름: 상속받을 클래스 이름 {

}

지정 생성자를 재정의 할 때는 override 키워드를 붙여야 한다. 자식 클래스에서 지정 생성자를 편의 생성자로 변경할 수도 있지만 이때도 override 를 붙여야 한다.

 

부모 클래스의 편의 생성자자식 클래스에서 직접 호출할 수 없다.

부모 클래스의 생성자와 동일한 이름을 사용하는 경우 override를 붙여줘야 한다.

 

 

https://icksw.tistory.com/49

 

[Swift 문법] Swift 공식 문서 정리 - 14 - Initialization (생성자)

이번 글에서는 Swift 공식 문서의 14번째 단원인 Initialization을 읽고 정리한 글을 쓰려고 한다. Apple Swift 공식 문서 14단원 - Initialization Initialization Initialization(생성자)는 클래스, 구조체, 열..

icksw.tistory.com

1.1 사용

  • final 키워드를 사용하면 함수 재정의(override)를 방지할 수 있습니다.
    final func sayHello( ) { }
  • static 키워드를 사용해 타입 메서드를 만들면 재정의가 불가능 합니다.
    static func typeMethod( ) { }
  • class 키워드를 사용해 타입 메서드를 만들면 재정의가 가능합니다.
    class func classMethod( ) { }
  • class 앞에 final을 붙이면 static 키워드를 사용한것과 동일하게 동작합니다.
    final class func finalClassMethod( ) { }
    == static func Method( ) { }
  • override 키워드를 사용해 부모 클래스의 메서드를 재정의 할 수 있습니다.
    override func selfIntroduce( ) { }
    override class func classMethod( ) { }
// 기반 클래스 Person
class Person {
    var name: String = ""
    
    func selfIntroduce() {
        print("저는 \(name)입니다")
    }
    
    // final 키워드를 사용하여 재정의를 방지할 수 있습니다
    final func sayHello() {
        print("hello")
    }
    
    // 타입 메서드
    // 재정의 불가 타입 메서드 - static
    static func typeMethod() {
        print("type method - static")
    }
    
    // 재정의 가능 타입 메서드 - class
    class func classMethod() {
        print("type method - class")
    }
    
    // 재정의 가능한 class 메서드라도 
    // final 키워드를 사용하면 재정의 할 수 없습니다
    // 메서드 앞의 `static`과 `final class`는 똑같은 역할을 합니다
    final class func finalCalssMethod() {
        print("type method - final class")
    }
}

// Person을 상속받는 Student
class Student: Person {
	// var name: String = "" // 상속받은 프로퍼티이기 때문에 써주지 않음
    var major: String = ""
    
	override func selfIntroduce() {
        print("저는 \(name)이고, 전공은 \(major)입니다")
        // super.selfIntroduce() // 부모 메서드 호출
    }
    
    override class func classMethod() {
        print("overriden type method - class")
    }
    
    // static을 사용한 타입 메서드는 재정의 할 수 없습니다
//    override static func typeMethod() {    }
    
    // final 키워드를 사용한 메서드, 프로퍼티는 재정의 할 수 없습니다
//    override func sayHello() {    }
//    override class func finalClassMethod() {    }

}

1.2 convenience 생성자

convenience init(parameters) {
	statement
}

편의 생성자는 인스턴스를 생성할 때 편리한 방식을 제공하기 위한 것이다.

일반적으로 파라미터가 없거나 적고, 지정 생성자는 생성자 파라미터에 프로퍼티를 상세하게 지정하는 경우가 일반적이다.

 

편의 생성자는 최종적으로 지정 생성자를 호출해야 한다.
( 같은 클래스의 지정 생성자 self.init() )

부모 클래스의 생성자를 자식클래스에서 convenience 생성자로 override 할 수 있다.

-> 자신이 가지고 있는 지정 생성자를 호출해야 한다.

1.3 생성자 규칙

  1. 부모 클래스의 생성자를 호출하기 전에 현재 클래스의 생성자 내에서 모든 프로퍼티가 초기화 되어있어야 한다.

  2. super.init()을 호출하기 전까지 self 를 사용할 수 없다

  3. 부모클래스에서 상속받은 프로퍼티의 값은 부모 생성자를 호출한 후 변경

  4. convenience init
    편의 생성자에서 가장 처음 하는 동작은 다른 생성자를 호출하는 것

  5. 생성자 자동 상속 규칙
    - 자식 클래스에서 지정 생성자를 따로 만들지 않은 경우, 부모 클래스의 모든 지정 생성자가 상속됨
    - 자식 클래스에서 부모 클래스의 모든 지정 생성자를 상속 / override 했다면 자식 클래스는 부모 클래스의 모든 편의 생성자를 상속 받게 됨
    - 지정 생성자를 재정의 할 때는 override 키워드 붙여야 함

https://windroamer.wordpress.com/2017/08/24/swift-%EC%83%9D%EC%84%B1%EC%9E%90/

 

Swift – 생성자

개인적으로 스위프트가 문법 구조가 맛깔나서 매력적인 언어임에는 틀림 없지만 쉬운 언어는 절대 아니라고 생각한다. 그 이유는 여러가지 지켜야 할 사항이 많기 때문이다. 어렵다는건 두가지

windroamer.wordpress.com

2. 인스턴스 생성 / 소멸

인스턴스를 생성하는 이니셜라이저와 클래스의 인스턴스가 소멸될 때 호출되는 디이니셜라이저, 그리고 이와 관련된 것들에 대해 알아봅니다.

  • 프로퍼티 초기값
  • 이니셜라이저 init
  • 디이니셜라이저 deinit

1. 프로퍼티 초기값

  • 스위프트의 모든 인스턴스는 초기화와 동시에 모든 프로퍼티에 유효한 값이 할당되어 있어야 합니다.
  • 프로퍼티에 미리 기본값을 할당해두면 인스턴스가 생성됨과 동시에 초기값을 지니게 됩니다.

2. init 이니셜라이저

  • 프로퍼티 초기값을 지정하기 어려운 경우에는 이니셜라이저 init을 통해 인스턴스가 가져야 할 초기값을 전달할 수 있습니다.

프로퍼티의 초기값이 꼭 필요 없을 때

  • 옵셔널을 사용!
  • class 내부의 init을 사용할때는 convenience 키워드 사용
class PersonC {
    var name: String
    var age: Int
    var nickName: String?
    
    init(name: String, age: Int, nickName: String) {
        self.name = name
        self.age = age
        self.nickName = nickName
    }

// 위와 동일한 기능 수행
// convenience init(name: String, age: Int, nickName: String) {
//       init(name: name, age: age)
//       self.nickName = nickName
//  }
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

let jenny: PersonC = PersonC(name: "jenny", age: 10)
let mike: PersonC = PersonC(name: "mike", age: 15, nickName: "m")

 

생성자에서 다른 생성자를 호출하는 경우  : convenience

 

  • 암시적 추출 옵셔널은 인스턴스 사용에 꼭 필요하지만 초기값을 할당하지 않고자 할 때 사용

3. 실패 가능한 이니셜라이저

  • 이니셜라이저 매개변수로 전달되는 초기값이 잘못된 경우 인스턴스 생성에 실패할 수 있습니다.
  • 인스턴스 생성에 실패하면 nil을 반환합니다.
    성공하면 정상적으로 초기화 됨
  • 실패가능한 이니셜라이저의 반환타입은 옵셔널 타입입니다.
  • init?을 사용합니다.
class PersonD {
    var name: String
    var age: Int
    var nickName: String?
    
    init?(name: String, age: Int) {
        if (0...120).contains(age) == false {
            return nil
        }
        
        if name.characters.count == 0 {
            return nil
        }
        
        self.name = name
        self.age = age
    }
}

//let john: PersonD = PersonD(name: "john", age: 23)
let john: PersonD? = PersonD(name: "john", age: 23)
let joker: PersonD? = PersonD(name: "joker", age: 123)
let batman: PersonD? = PersonD(name: "", age: 10)

print(joker) // nil
print(batman) // nil

4. 디이니셜라이저

  • deinit은 클래스의 인스턴스가 메모리에서 해제되는 시점에 호출됩니다.
  • 인스턴스가 해제되는 시점에 해야할 일을 구현할 수 있습니다.
  • deinit 매개변수를 지닐 수 없습니다.
  • 자동으로 호출되므로 직접 호출할 수 없습니다.
  • 디이니셜라이저는 클래스 타입에만 구현할 수 있습니다.
  • 인스턴스가 메모리에서 해제되는 시점은 ARC(Automatic Reference Counting) 의 규칙에 따라 결정됩니다.
class PersonE {
    var name: String
    var pet: Puppy?
    var child: PersonC
    
    init(name: String, child: PersonC) {
        self.name = name
        self.child = child
    }
    
    // 인스턴스가 메모리에서 해제되는 시점에 자동 호출
    deinit {
        if let petName = pet?.name {
            print("\(name)가 \(child.name)에게 \(petName)를 인도합니다")
            self.pet?.owner = child
        }
    }
}

var donald: PersonE? = PersonE(name: "donald", child: jenny)
donald?.pet = happy
donald = nil // donald 인스턴스가 더이상 필요없으므로 메모리에서 해제됩니다
// donald가 jenny에게 happy를 인도합니다

https://minmong.tistory.com/161

 

Swift 기초 문법 - Class(클래스)를 정리하기

Swift의 클래스 역시 구조체처럼 관계가 있는 것들을 묶어서 표현할 때 사용됩니다. 구조체와 마찬가지로 기본적인 구조는 프로퍼티와 메서드로 구성되어있습니다. 구조체를 클래

minmong.tistory.com

 

반응형
Comments