[야우쓰] 3주차(1) 구조체 초기화

hello_hidi·2022년 11월 28일
0

야우쓰

목록 보기
14/20
post-thumbnail

초기화

구조체 / 열거형 / 클래스의 인스턴스를 생성하는 것

초기화의 역할은 모든 프로퍼티를 기본값으로 초기화 하는 것이다.
인스턴스 내 기본값이 존재하지 않는 프로퍼티가 있을 경우 초기화에 실패하고 인스턴스는 생성되지 않는다!

왜 초기화를 해야 되나?

스위프트는 에러에 대한 안전을 최우선시 한다.
빈 메모리에 접근하게 된다면 예기치 못한 에러가 발생할 수 있다.
타입 내부에 프로퍼티가 있다면 해당 프로퍼티에는 무조건 값이 있다는 것을 보장해야 한다.

구조체 초기화 방법

1) 선언과 동시에 프로퍼티에 기본값 넣어주기

struct Human {
	let name : String = "희재"
    let age : Int = 23
}

let ryu = Human()
dump(ryu)

// - name : "희재"
// - age : 23

2) 프로퍼티의 타입을 옵셔널 타입으로 설정하기

값이 있을지 없을지 모르는 경우 옵셔널 타입으로 선언, 그러면 초기화할 때 옵셔널 타입인 name, age는 자동으로 nil로 초기화
=> 옵셔널 타입으로 선언하지 않으면 nil값을 받지 못함
var로 선언해야한다!

struct Human {
	var name :  String?
    var age : Int?
}

let ryu = Human()

let ryu2 = Human(nil, nil) 
dump(ryu2)
// - name : nil
// - age : nil

3) init 함수에서 값 설정해주기

초기화를 진행 하는 함수인 init함수 즉 생성자를 사용하여 생성자 안에서 해당 프로퍼티들을 초기화 시킬 수 있음.

  • 다양하게 선언할 수 있다.
  • 중요한건 init함수가 종료되기 전까진 모든 프로퍼티가 기본 값을 가져야한다!!!
struct Human {
	let name: String
    let age: Int
    
    // 다양하게 선언할 수 있다!
    init(name:String) {
    	self.name = name
        self.age = 23
    }
    
    init(name:String, age: Int) {
    	self.name = name
        self.age = age
    }
}
    
//but.. init함수 종료 전까지 모든 프로퍼티가 기본값을 가져야함
let ryu = Human(age:23) // error :  Incorrect argument label in call    

Memberwise Initializers

아래 코드처럼 구조체를 선언했다면 무조건 에러가 나야된다 왜?
1,2,3번에 해당하는 어떠한 초기화도 안해줬기 때문
but. 에러가 안난다.... why?

struct Human {
    let name : String
    let age : Int
}

Memberwise 생성자

구조체가 자동으로 제공하는 생성자로, 파라미터를 통해 모든 프로퍼티의 초기화를 가능하게 한다.
즉. 프로퍼티의 초기화를 따로 지정하지 않을경우, 초기화되지 않은 프로퍼티를 초기화할 수 있는init함수를 자동 제공해준다!!!!

struct Human {
    let name : String
    let age : Int
}

let ryu = Human.init("희재",23)

Memberwise 생성자 성질

1) memberwise initializers로 제공되는 생성자의 파라미터는, 프로퍼티가 선언된 순서와ㅗ 갯수에 맞추어 생성된다!

Human.init(name: "희재", age : 23)
Human.init( age : 23, name: "희재") // error
Human.init(name: "희재") // error

2) 프로퍼티가 let으로 선언되어 있고, 이미 초기화가 되어있으면 생성자 목록에서 제외된다.

why? 어차피 초기화해줘도 값이 수정이 안되기 때문!

struct Human {
    let name : String = "희재"
    let age : Int
}

Human.init(age: 23)
Human.init(name: "희재", age: 23) // error : Extra argument 'name' in call

3) 프로퍼티가 var 선언되어 있고, 이미 초기화가 된 상태면 해당 프로퍼티를 초기화 하는 생성자와 제외된 생성자 두개를 제공한다.

why? 2번이랑은 다르게 var로 선언되면 값이 수정될 가능성이 생기게 된다!
따라서 var로 선언되어 초기화가 된 프로퍼티가 포함된 생성자와 아닌 생성자 두가지를 각각 제공해준다

struct Human {
    var name : String = "희재"
    let age : Int
}

Human.init(age: 23) // name이 제외된 생성자
Human.init(name: "서린", age: 23)  // name이 포함된 생성자

4) 생성자를 직접 생성한 경우, memberwise initializers는 더이상 제공되지 않는다.

즉. 구조체 안에 init 함수를 직접 구현하지 않는 경우에만 제공됨

struct Human {
    var name : String = "희재"
    let age : Int
    
    init(name: String){
    	self.name = name
        self.age = 23
    }
}

Human.init(age: 23)

5) 둘다 사용하고 싶다면 extension

응 그럼 구조체 안에만 없으면 되는건가? 정답
이니셜라이저의 복잡성을 낮추고 이니셜라이저가 의도치 않게 사용되는 것을 방지하기 위함

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

extension Human {
	init(name: String) {
    	self.name = name
        self.age = 23
    }
}
Human.init(name: "희재") // 구조체 init 함수를 활용한 초기화
Human.init(name: "희재", age: 23) // memberwise initialize에서 제공한 생성자

6) 프로퍼티 중 하나라도 private라면 memberwise initializers는 제공되지 않는다.

struct Human {
	private var name: String
    var age: Int
}

Human.init // No completions 아무것도 제공하지 않는다.
profile
안뇽희디

0개의 댓글