반응형

참고 사이트: iOS 프로그래밍을 위한 스위프트 기초(edwith)
참고 문서: The Swift Language Guide (한국어)
실행 환경: Xcode 12 실행 → Create a new Xcode project → macOS → Command Line Tool 선택 → Product Name, Organization Identifier 입력 후 프로젝트 생성

 

목차

  1. 스위프트(Swift) 5 배워보기 - 1. 다양한 타입
  2. 스위프트(Swift) 5 배워보기 - 2. 함수, 제어문, 옵셔널
  3. 스위프트(Swift) 5 배워보기 - 3. 클래스, 구조체, 열거형
  4. 스위프트(Swift) 5 배워보기 - 4. 클로저
  5. 스위프트(Swift) 5 배워보기 - 5. 프로퍼티
  6. 스위프트(Swift) 5 배워보기 - 6. 상속, 인스턴스 생성/소멸
  7. (계속)

 


상속

  • Swift에서 클래스가 다른 타입과 구분되는 근본적인 요소는 상속(Inheritance)이다.
  • 클래스는 메소드, 프로터피 등을 다른 클래스로부터 상속할 수 있다.
  • 단일 상속만 가능하며, 다중 상속은 지원하지 않는다.
  • 여러 사용법
    • final 키워드를 사용하여 재정의(Override)를 방지할 수 있다.
    • static 키워드를 사용하여 타입 메소드를 만들면 재정의가 불가능하다.
    • class 키워드를 사용하여 타입 메소드를 만들면 재정의가 가능하다.
    • class 앞에 final을 붙이면 static 키워드를 사용한 것과 동일하다.
    • override 키워드를 사용하여 부모 클래스의 메소드를 재정의할 수 있다.
// 기반 클래스 Person 정의
class Person {
    // name 저장 프로피터 선언
    var name: String = ""
    
    // selfIntroduce() 메소드 선언
    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 major: String = ""
    
    override func selfIntroduce() {
        print("저는 \(name)이고, 전공은 \(major)입니다")
    }
    
    override class func classMethod() {
        print("overriden type method - class")
    }
    
    // static을 사용한 타입 메소드는 재정의 할 수 없다.
    // override static func typeMethod() {    }
    
    // final 키워드를 사용한 메소드, 프로퍼티는 재정의 할 수 없다.
    // override func sayHello() {    }
    // override class func finalClassMethod() {    }
}


// 객체 생성 후 사용
let nyebo: Person = Person()
let jaehyuk: Student = Student()

nyebo.name = "nyebo"
jaehyuk.name = "jaehyuk"
jaehyuk.major = "Swift"

nyebo.selfIntroduce() // 저는 nyebo입니다

jaehyuk.selfIntroduce() // 저는 jaehyuk이고, 전공은 Swift입니다

Person.classMethod() // type method - class

Person.typeMethod() // type method - static

Person.finalCalssMethod() // type method - final class

Student.classMethod() // overriden type method - class

Student.typeMethod() // type method - static

Student.finalCalssMethod() // type method - final class

 

 

인스턴스 생성/소멸

  • 인스턴스 생성초기화(Initialization), 인스턴스 소멸초기화 해지(Deinitialization)라고 한다.

 

프로퍼티 초기화

  • 모든 인스턴스는 초기화와 동시에 모든 프로퍼티에 유효한 값이 할당되어 있어야 한다.
class PersonA {
    // 모든 저장 프로퍼티에 기본값 할당
    var name: String = "unknown"
    var age: Int = 0
    var nickName: String = "nick"
}

// 인스턴스 생성
let nyebo: PersonA = PersonA()

// 기본값이 인스턴스가 지녀야 할 값과 맞지 않다면
// 생성된 인스턴스의 프로퍼티에 각각 값 할당
nyebo.name = "nyebo"
nyebo.age = 34
nyebo.nickName = "n"

print(nyebo.name)     // nyebo
print(nyebo.age)      // 34
print(nyebo.nickName) // n

 

초기화(init)

  • 만약, 초기값을 지정하기 어려운 경우, 초기화(init)를 통해 인스턴스가 생성 시 가져야 할 초기값을 전달할 수 있다.
  • 옵셔널 사용 시 초기값을 생략할 수 있다.
class PersonB {
    // 저장 프로퍼티 선언 시에 값을 미리 할당하지 않고,
    var name: String
    var age: Int
    var nickName: String // 옵셔널
    
    // init으로 인스턴스 생성 시 필요한 초기값을 전달할 수 있다.
    init(name: String, age: Int, nickName: String) {
        self.name = name
        self.age = age
        self.nickName = nickName
    }
}

class PersonC {
    var name: String
    var age: Int
    var nickName: String? // 옵셔널
    
    // 옵셔널 지정한 nickName을 생략할 수 있다.
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

// init으로 전달된 초기값을 사용하여 인스턴스를 생성할 수 있다.
let jaehyuk: PersonB = PersonB(name: "jaehyuk", age: 34, nickName: "재혁")
let nyebo: PersonC = PersonC(name: "nyebo2", age: 34)

// 인스턴스 생성 후 옵셔널 지정한 nickName에 값을 할당할 수 있다.
nyebo.nickName = "녜보"
print(nyebo.nickName!) // 녜보

 

  • 초기값이 잘못된 경우 인스턴스 생성에 실패할 수 있다. 옵셔널 init?을 사용하면, 인스턴스 생성 실패 시 nil을 반환한다.
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.count == 0 {
      return nil
    }
    
    self.name = name
    self.age = age
  }
}

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) // age 초기값이 기준 범위를 넘어, nil이 반환된다.
print(batman) // name 초기값이 빈 값으로, nil이 반환된다.

 

  • 모든 서브클래스에서 반드시 구현해야 하는 필수 초기값에는 required 키워드를 붙여준다.
class SomeClass {
    required init() {
    }
}

// 필수초기값을 상속받은 서브클래스에서도 반드시 required 키워드를 붙여
// 다른 서브클래스에게도 이 초기값은 필수초기값이라는 것을 알려야 한다.
class SomeSubclass: SomeClass {
    required init() {
    }
}

 

초기화 해제(deinit)

  • deinit은 인스턴스가 메모리에서 해제되는 시점에 호출된다.
  • deinit을 통해 인스턴스 해제 시점에 해야할 일을 구현할 수 있다.
  • 자동으로 호출되므로 직접 호출할 수 없다.
class PersonE {
  var name: String
  var pet: String
  var child: String
  
  init(name: String, pet: String, child: String) {
    self.name = name
    self.pet = pet
    self.child = child
  }
  
  // 인스턴스가 메모리에서 해제되는 시점에 자동 호출
  deinit {
     print("\(name)가 \(child)에게 \(pet)를 인도합니다")
  }
}

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

 

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기