大器晩成

초기화(initializer) 본문

iOS/Swift 문법

초기화(initializer)

zerobugpark 2024. 11. 21. 21:20

 

명시적 초기화란

  • 프로퍼티를 선언하면서 동시에 초기값을 지정하는 경우입니다.
  • 초기화 메서드 내에서 프로퍼티의 초기값을 지정하는 경우입니다.

구조체의 프로퍼티와 초기화 구문

struct Person {
    var name: String
    var age: Int
}

//var person = Person() // 모든 속성이 초기화 되지 않았기 때문에 에러 발생
var person = Person(name: "카리나", age: 25) // 멤버와이즈초기 구문
  • 멤버와이즈 초기화 구문은 인스턴스를 생성하는 형식을 정의할 뿐만 아니라, 입력된 인자값을 이용하여 프로퍼티를 초기화하는 과정까지 처리합니다.
  • 기본 초기화 구문 클래스/구조체이름(), 이 형식의 초기화 구문을 사용하려면, 객체의 모든 프로퍼티는 선언과 동시에 초기값이 지정되어 있어야 합니다.

 

 클래스의 프로퍼티와 초기화 구문

// 클래스 생성과 함께 초기화를 지정하지 않으면 오류가 발생한다.
//class Dog {
//    var name: String
//    var weight: Double
//}

class Dog {
    var name: String = "강아지"
    var weight: Double = 0.0
    var height: Double?
}
var dog = Dog()
  • 클래스의 프로퍼티는 정의할 때 초기값을 주던가, 아니면 옵셔널 타입으로 선언합니다.
  • 인스턴스를 생성할 때에는 클래스명 뒤에()를 붙여준다.
  • 클래는 구조체와 다르게 멤버와이즈 형식의 초기화 구문이 제공되지 않습니다. (클래스는 상속기 있기 때문에 지원 X)
  • 클래스에서 제공되는 것은 빈 괄호 형태의 기본 초기화 구문입니다. 이때, 모든 프로퍼티가 선언과 동시에 초기화되어 있을 때에만 사용할 수 있다. 만약 초기화되지 않은 프로퍼티가 있다면 기본 초기화 구문은 사용할 수 없으며, 이때에는 직접 초기화 구문을 정의해서 내부에서 해당 프로퍼리를 초기화해주어야 합니다.

 

초기화 메서드 / 이니셜라이저(initializer)

- 생성자(이니셜라이즈)는 인스턴스를 만들 때 사용하는 특별한 메서드입니다.

// Init 초기화 메소드

//init (<매개변수> : <타입>, <매개변수>: <타입>, ....) {
//    1. 매개변수의 초기화
//    2. 인스턴스 생성 시 기타 처리할 내용
//}

struct Resolution {
    var width = 0
    var heigth = 0
    
    //초기화 메소드 : Width를 인자값으로 받음
    init (width: Int) {
        self.width = width
    }
}

// Resolution 구조체에 대한 인스턴스를 생성
let resoultion = Resolution.init(width: 4096)
//let resoultion = Resolution(width: 4096) // init은 생략 가능

class VideoMode {
    var resolution = Resolution(width: 2048)
    var interlaced = false
    var frameRate = 0.0
    var name: String?
    
    //초기화 메소드: interlaced, frameRate 두 개의 인자값을 받음
    init(interlaced: Bool, frameRate: Double) {
        self.interlaced = interlaced
        self.frameRate = frameRate
    }
}
// VideoMode 클래스에 대한 객체를 생성
let videoMode = VideoMode.init(interlaced: true, frameRate: 40.0)
//let videoMode = VidoeMode(interlaced: true, frameRate: 40.0) // init은 생략 가능
    • 구조체나 클래스는 모두 정의된 내용을 그대로 사용할 수는 없습니다. 항상 인스턴스를 생성해서 메모리 공간을 할당받은 다음에 사용해야 한다. 이를 초기화라고 합니다. 
    • 초기화과정에서 가장 중요한 것은 저장 프로퍼티이다. 모든 저장 프로퍼티는 인스턴스 생성과정에서 초기화되어야 하며, 이를 위해서는 반드시 초기값이 지정되어 있어야 한다.
    • 모든 저장 프로퍼티에 초기값이 지정되어 있다면 기본 초기화 구문을 사용하여 인스턴스를 생성할 수 있습니다.
      ex) Resolution() , Video()
    • 초기화 메서드는 형태나 문법은 다를지라도 다른 객체 지향 언어에서도 찾아볼 수 있으며, 인스턴스가 생성될 때의 형식과 할 일을 정의한다고 하여 생성자(Constructor)라고 부르기도 합니다.
    • 생성자의 목적은 "저장속성 초기화"입니다.
    • 클래스, 구조체, (열거형)은 모두 설계도 일뿐이고, 실제 데이터(속성), 동작(메서드)을 사용하기 위해서는 ===> 초기화 과정이 반드시 필요합니다
    • 인스턴스 초기화 완료 -> 메모리에 정상적으로 인스턴스가 생김

 

스위프트에서 초기화 메서드는 다소 특수한 메서드의 일종이기 때문에 몇 가지 특성을 가집니다.

  • 초기화 메서드의 이름은 init으로 통일됩니다.
  • 매개변수의 개수, 이름, 타입은 임의로 정의할 수 있습니다.
  • 매개변수의 이름과 개수, 타입이 서로 다른 여러 개의 초기화 메서드를 정의할 수 있습니다.
  • 정의된 초기화 메서드는 직접 호출되기도 하지만, 대부분 인스턴스 생성 시 간접적으로 호출된다.

 

init초기화 메서드의 오버로딩

class VideoMode2 {
   
    var interlaced = false
    var frameRate = 0.0
    var name: String?
    
    
    // 초기화될 때 name 인자값만 받는 init 구문
    init(name: String) {
        self.name = name
    }
    
    //초기화될 때 interlaced 인자값만 받는 init 구문
    init(interlaced: Bool) {
        self.interlaced = interlaced
    }
    
    //초기화 메소드: interlaced, frameRate 두 개의 인자값을 받음
    init(interlaced: Bool, frameRate: Double) {
        self.interlaced = interlaced
        self.frameRate = frameRate
    }
    
    //초기화될 때 Interlaced, frameRate, name 세 개의 인자값을 받는 init 구문
    init(interlaced: Bool, frameRate: Double, name: String) {
        self.interlaced = interlaced
        self.frameRate = frameRate
        self.name = name
    }
    
}
// VideoMode 클래스에 대한 인스턴스를 생성하고 상수에 할당
let nameVideoMode = VideoMode2(name: "홍길동")
let simpleVideoMode = VideoMode2(interlaced: true)
let doubleVideoMode = VideoMode2(interlaced: true, frameRate: 40.0)
let tripleVideoMode = VideoMode2(interlaced: true, frameRate: 40.0, name: "홍길동")
//let test = VideoMode2() // init 메소드를 추가한 후, 기본 초기화 구문을 이용해서 객체를 생성시 오류
  • 모든 저장 프로퍼티가 초기화되어 있을 때, 구조체와 클래스는 빈 인자값 형식의 초기화 구문을 제공한다. 하지만 Init 메서드가 작성되고 나면 어떤 인자값 형식을 갖는가에 상관없이 그 객체의 기본 초기화 구문은 제공되지 않습니다.
  • init 메서드를  추가하고 나면 더 이상 기본 초기화 구문이 제공되지 않는 특성은 구조체의 멤버와이즈 초기화구문에도 동일하게 적용합니다. 따라서 구조체에 init 메서드를 추가할 때에는 특히 주의해야 합니다.
  • 다양한 파라미터 조합으로 생성자를 여러 개 구현 가능합니다.
  • 여러 가지 방식으로 인스턴스를 생성하는 방법을 제공합니다.

 

생성자(이니셜라이저)와 self 키워드

class Pokemon {
    var name: String //self 키워드가 가리키는 프로퍼티
    var weight: Int //self 키워드가 가리키는 프로퍼티
    
    init(name: String, weight: Int) {
        //name = name //파라미터와 동일하기 때문에 에러가 발생한다.
        self.name = name
        self.weight = weight
    }
    
    func fight() {
        print("\(self.name) 몬스터볼에서 나왔습니다.")
    }
    
    func back() {
        print("\(name) 몬스터볼로 돌아갔습니다.")
    }
}


// 인스턴스내에서 동일한 변수명, 상수명을 사용할때
// 가르키는 것을 명확하게 하기 위해 self키워드를 사용
  • self 키워드는 클래스/구조체 내에서 해당 인스턴스(자기 자신)를 가리킵니다.

 

옵셔널 타입의 초기화 - 속성이 옵셔널 타입인 경우

class Pokemon {
    var name: String?
    var weight: Int
    
    init(weight: Int) {
        self.weight = weight
    }
    
    func fight() {
        print("\(self.name) 몬스터볼에서 나왔습니다.")
    }
    
    func back() {
        print("\(name) 몬스터볼로 돌아갔습니다.")
    }
}

var pokemon = Pokemon(weight: 10)
pokemon.name
print(pokemon.name) // nil
print(pokemon.weight) // 10

pokemon.back() // 출력: nil 몬스터볼로 돌아갔습니다.
  • 옵셔널타입을 가진 변수의 경우는 반드시 초기값이 있을 필요는 없습니다 -> nil로 초기화되기 때문입니다.

 

초기화 정리 ⭐️

초기화
  • 구조체나 클래스 이름 뒤에 빈 괄호를 붙이면 기본적인 인스턴스가 만들어집니다.
  • 필요에 따라 빈 괄호가 아닌 인자값을 넣어주기도 하는데, 이때 입력되는 인자값들은 대부분 객체의 프로퍼티를 초기화하기 위해 반드시 필요한 값들입니다.
  • 스위프트에서 옵셔널 타입으로 선언되지 않은 모든 프로퍼티는 명시적으로 초기화해야 합니다.
  • 클래스나 구조체는의 모든 프로퍼티는 적어도 인스턴스가 생성되는 시점까지는 반드시 초기화가 되어야 합니다.
  • 구조체는 모든 프로퍼티를 입력받아 초기화하는 기본 초기화 구문을 자동으로 제공합니다.
  • 프로퍼티를 보통 멤버 변수라고 부르는 까닭에, 이 초기화 구문을 멤버와이즈 초기화구문 (Memberwise Initializer이라고 합니다.

 

728x90

'iOS > Swift 문법' 카테고리의 다른 글

지연 저장 속성 (Lazy Stored Properties)  (0) 2024.11.21
저장속성(Stored Properties)  (0) 2024.11.21
클래스와 구조체의 차이  (0) 2024.11.21
구조체(Struct)와 클래스(Class)  (1) 2024.11.21
옵셔널 체이닝  (4) 2024.11.12