Swift/문법 및 이론

Swift : 기초문법 [인스턴스 #2 기본 이니셜라이저, 멤버와이즈 이니셜라이저]

서근 2022. 1. 14.
공지사항
사파리보다는크롬으로 접속을 권장합니다
사파리로 접속시 gif 파일이 표시되지 않을 수 있습니다

본 게시글은 yagom님의 Swift 프로그래밍 3판을 참고하여 작성되었습니다.

 

기본 이니셜라이저와 멤버와이즈 이니셜라이저

저번 게시글에서는 사용자 정의 이니셜라이저에 대해 알아봤는데, 이번에는 기본 이니셜라이저와 멤버와이즈 이니셜라이저에대해 알아볼까 한다. 

 

만약 사용자 정의 이니셜라이저를 정의해주지 않으면 클래스나 구조체는 모든 프로퍼티에 기본값이 지정되어있다는 전제로 기본 이니셜라이저를 사용하게 된다. 기본 이니셜라이저는 프로퍼티 기본값으로 초기화해서 인스턴스를 생성한다.

  • 저장 프로퍼티에 기본값이 있고, 사용자 정의 이니셜라이저가 지정되어 있지 않으면 ➜ 기본 이니셜라이저 제공

저장 프로피티를 선언할 때 기본값을 정해주지 않았다면 이니셜라이저에서 초깃값을 설정해야 하는데, 이 때문에 매번 이니셜라이저를 추기/변경 하는 일은 귀찮기 때문에 구조체는 사용자 정의 이니셜라이저를 구현하지 않았다면 프로퍼티의 이름으로 매개변수를 갖는 이니셜라이저인 멤버와이즈 이니셜라이저를 기본으로 제공한다. 

 

하지만, 클래스 멤버와이즈 이니셜라이저는 지원하지 않으니 주의!

 

모든 Swift 구조체는 기본적으로 합성된 Memberwise initializer를 얻는다.

struct Employee {
    var name: String = "anonymous"
    var height: Int = 200
}

let Seogun: Employee = Employee(name: "서근", height: 100)
let Mijin: Employee = Employee(name: "미진", height: 150)

//구조체의 저장 프로퍼티에 기본값이 있는 경우
//필요한 매개변수만 사용하여 초기화할 수도 있다.
let Someone: Employee = Employee()
let Someone2: Employee = Employee(height: 120)
print(Someone2) //Employee(name: "anonymous", height: 120)
let Someone3: Employee = Employee(name: "익명")
print(Someone3) //Employee(name: "익명", height: 200)

이 이니셜라이저를 사용하면 구조체를 쉽게 사용할 수 있지만, Swift는 이것을 만드는 두 가지 추가 작업을 수행한다.

 

첫 번째, 프로퍼티에 기본값이 있는 경우 이니셜라이저에 기본 매개변수 값으로 통합된다.

struct User {
    var name: String
    var yearsActive = 0
}

그런 다음 두 가지 방법 중에 하나로 만들 수 있다.

struct Employee {
    var name: String
    var yearsActive = 0
}

let Seogun = Employee(name: "서근")
let Mijin = Employee(name: "미진", yearsActive: 19)

print("제 이름은 \(Seogun.name)입니다.")
print("\(Mijin.name)은 \(Mijin.yearsActive)살 입니다.")

이렇게 하면 필요한 부분만 채울 수 있기 때문에 더 쉽게 만들 수 있다.

 

두 번째, custom initializer를 생성하는 경우 Memberwise initializer를 제거하는 것이다.

 

예를 들어 익명의 직원을 만든 custom initializer의 경우 다음과 같다.

struct Employee {
    var name: String
    var yearsActive: Int?
    
    init(name: String) {
        self.name = "익명"
        print("익명의 직원을 생성합니다..")
    }
}

let Seogun = Employee(name: "서근")

init을 작성하여 구조체의 기본값을 정해줬는데, 이래 코드를 보면 오류가 났다!

let Seogun = Employee(name: "서근")
let Mijin = Employee(name: "미진", yearsActive: 19)
"더 이상 Memberwise 이니셜라이저에 의존할 수 없습니다. 이 작업을 수행할 수 없습니다."

위에서 사용자 정의 이니셜라이저를 만들었고, Swift가 멤버와이즈 이니셜라이저를 그대로 두면 이니셜라이저에 작성한 중요한 작업이 누락될 수도 있다.

 

따라서 Struct에 대한 custom initializer 를 추가하는 즉시 기본 custom initializer가 사라진다.

 

이 상태를 유지하려면 다음과 같이 custom initializerextentsion으로 이동해야 한다.

struct Employee {
    var name: String
    var yearsActive = 0
}
    
    extension Employee {
        init() {
            self.name = "익명"
            print("익명의 직원을 생성합니다..")
        }
    }


let Seogun = Employee(name: "서근")
let Mijin = Employee(name: "미진", yearsActive: 19)

let anonymous = Employee()

print("제 이름은 \(Seogun.name)입니다.")
print("\(Mijin.name)은 \(Mijin.yearsActive)살 입니다.")

/*
익명의 직원을 생성합니다..
제 이름은 서근입니다.
미진은 19살 입니다.
*/

struct Employee {
    var name: String
    var height: Int?
}

extension Employee {
    init() {
        self.name = "익명"
        print("익명의 누군가를 생성합니다.")
    }
}
var Seogun: Employee = Employee(name: "서근", height: 100)
print(Seogun)
//Employee(name: "서근", height: Optional(100))

var Mijin: Employee = Employee(name: "미진")
Mijin.height = 200
//Employee(name: "미진", height: Optional(150))
print(Mijin)

let Someone3: Employee = Employee()
print(Someone3)
//익명의 누군가를 생성합니다.
//Employee(name: "익명", height: nil)

예시

struct Country {
    var name: String
    var usesImperialMeasurements: Bool
    init(countryName: String) {
        
        name = countryName
        
        let imperialCountries = ["서울", "도쿄", "뉴욕"]
       
        if imperialCountries.contains(name) {
            usesImperialMeasurements = true
            print("정답")
        } else {
            usesImperialMeasurements = false
            print("실패")
        }
    }
}
Country.init(countryName: "서울")
//정답
struct Message {
    var from: String
    var to: String
    var content: String
    init() {
        from = "서근"
        to = "미진"
        content = "Yo"
    }
}
let message = Message()
struct Cabinet {
    var height: Double
    var width: Double
    var area: Double
    init (itemHeight: Double, itemWidth: Double) {
        height = itemHeight
        width = itemWidth
        area = height * width
    }
}
let drawers = Cabinet(itemHeight: 1.4, itemWidth: 1.0)

print("height(\(drawers.height)) 곱하기 width(\(drawers.width))는 \(drawers.area) 입니다.")
struct PowerTool {
    var name: String
    var price: Int
}
let drill = PowerTool(name: "전동드릴", price: 32_000)

print("\(drill.name)의 가격은 \(drill.price)원 입니다.")
//전동드릴의 가격은 32000원 입니다.

TIP
 
 

클래스에서 멤버와이즈 이니셜라이저
클래스에서는 멤버와이즈 이니셜라이저를 지원하지 않는다. 멤버와이즈 이니셜라이저는 오직 구조체에서 만의 특권이다.

 

 

읽어주셔서 감사합니다🤟

 

 

 

728x90
  • 이전글
  • 다음글