관리 메뉴

사과하는 제라스

[Swift 문법] 속성의 종류에 따른 Memberwise Initializer의 접근 지정자 본문

제라스의 iOS 공부/Swift 문법

[Swift 문법] 속성의 종류에 따른 Memberwise Initializer의 접근 지정자

Xerath(제라스) 2024. 5. 7. 02:32

목차

    728x90
    반응형

    서론

    안녕하세요! 제라스입니다~!!  🤖:-D🤖

     

    아니...제가 지난주에 공부를 하다가 같은 러너인 피카한테 다음과 같은 질문을 받았어요...!!

     

    import UIKit
    
    struct Student {
        var name: String
        var location: String
        private var bestFriend = "Nobody"
    }

     

    이런 식으로 struct를 구현하면 name, location은 init해주면 되지만,

    bestFriend는 값이 들어있으니 init해주지 않아도 되는 것 아니냐는...?!?!?!

     

    어...그러게여?? 하하하...

     

    알고보니 private 속성이 하나라도 있으면 Memberwise Initializer도 private으로 설정이 된다고 하더군요...!

    그래서 결국 외부에서 사용을 못하게 되니 따로 생성자를 만들어줘야 합니다!

    이 이유는 뒤에서 조금 더 자세히 다뤄보겠습니다!

     

    그럼 한번 포스팅 시작해보겠습니다!

    Default Initializer(기본 생성자)

    일단 이 친구는 아무 값도 안 넣어줘도 되는 친구! 이렇게 보시면 됩니다.

    기본 생성자는 class, struct 두 군데에서 제공이 될 수 있는데

    class

    클래스에서는 모든 속성이 초기값을 가져야 기본 생성자가 제공돼요~!!

    즉, 값이 들어있어야만 제공이 된다는 건데,

    이때 값이 안 들어있고 타입이 Optional이어도 초기화가 되어있다고 생각하고 기본 생성자를 제공해주죠 ㅎㅎ

     

    하지만 속성들 중 하나라도 초기값을 지니지 않는다면(Optional도 아니라면) 기본 생성자는 제공되지 않고 모든 속성이 초기화가 될 수 있는 init을 한개라도 명시적으로 제공해야 합니다!

    즉, '어? 너 기본은 하랬지? 기본도 안돼? 그럼 내가 도와줄 수가 읎다잉~' 이런 셈이죠ㅋㅋㅋㅋㅋ

     

    그리고 또 하나! 기본 생성자를 제공받을 수 있는 조건이더라도 명시적으로 init을 구현한 경우엔 제공받지 못합니다!

    마치, '어? 내가 제공해주려고 했는데... 아주 배가 불렀지?? 그럼 넌 그거로 init해라~! 난 지원 안해준다!' 이런 느낌으로 제공을 받지 못합니다.

    struct

    구조체도 클래스와 마찬가지로 모든 속성이 초기값을 갖거나 Optional이기라도 해야 기본 생성자를 제공해줍니다!

    만약 그렇지 않을 경우 구조체도 기본 생성자를 제공받지 못합니다.

    하지만 걱정하지 않아도 됩니다. 어차피 Memberwise Initializer는 늘 제공되고 있어서 이걸 쓰면 되니까요ㅎㅎ

     

    그리고 구조체도 init을 명시하는 순간 기본 생성자는 제공받지 못합니다...!

     

    참 둘이 비슷한 양상을 띄죠.

    Memberwise Initializer(멤버와이즈 생성자)

    오늘의 중요한 녀석입니다!

    얘 때문에 학습하게 된거라 ㅋㅋㅋㅋㅋㅋㅋ

     

    일단 위에서 언급한 것처럼 struct는 Memberwise Initializer가 늘 제공됩니다.

    struct Student {
        var name: String
        var location: String
        var bestFriend = "Nobody"
    }
    
    // 이렇게 초기화 안된 것만도 가능한 멤버와이즈 생성자
    let yoon1 = Student(name: "Xerath Yoon", location: "Pohang")
    
    // 모두 초기화하는 멤버와이즈 생성자
    // 이게 기본 멤버와이즈 생성자
    let yoon2 = Student(name: "Xerath Yoon", location: "Pohang", bestFriend: "Somebody")

     

    이렇게 초기화되지 않은 친구들이 있어도 멤버와이즈 생성자는 제공이 됩니다.

    struct Student {
        var name: String
        var location: String?
        var bestFriend = "Nobody"
    }
    
    let yoon3 = Student(name: "Xerath Yoon")

     

    위처럼 Optional이 있으면 초기화가 될 수 있다고(nil로) 판단해서 name만 채워줘도 되는 멤버와이즈 연산자를 제공해주죠.

     

    위 두 상황은 모두 기본 생성자가 제공이 되지 않아요.

    첫번째는 name, location이 초기화가 안 되어있고, 두번째는 name이 초기화가 안 되어있으니까요~~~

     

    그럼 제가 본질적으로 문제였던 속성의 접근제한자가 internal(var나 let 앞에 아무것도 안 써주면 internal임~~)이 아닌 다른 접근 제한자일 때를 보겠습니다.

    속성의 접근제한자 = 멤버와이즈 생성자의 접근제한자

    제곧내입니다 ㅋㅋㅋㅋㅋㅋㅋ

    일단 Swift의 공식문서에서 Access Control부터 살펴보면 떡하니 나와있습니다.

     

    즉, 구조체에서 저장 속성(그냥 일반 상수나 변수~!)이 하나라도 private이라면 멤버와이즈 생성자는 private입니다.

    코드로 보면요!

    struct Student {
        var name: String
        var location: String?
        private var bestFriend = "Nobody"
    }
    
    // Error - 'Student' initializer is inaccessible due to 'private' protection level
    let yoon4 = Student(name: "Xerath Yoon")

     

    말 그대로 지금 일단 상황을 보면

    1. 기본 생성자? 없죠~(name이 초기화 안되어 있어서)

    2. 멤버와이즈 생성자? bestFriend가 private이라서 멤버와이즈 생성자가 private이기에 Student 구조체 바깥에서는 쓸 수가 없습니다.

     

    그럼 왜 그럴까요??????? 의문이 들잖아요ㅎㅎㅎ

    그래서 생각해보면...!!

    일단 멤버와이즈 생성자는 모든 속성에 대해서 접근이 가능해야 하고 값을 넣을 수 있어야 합니다.

    마치 우리가 위에서 

    struct Student {
        var name: String
        var location: String
        var bestFriend = "Nobody"
    }
    
    // 이렇게 초기화 안된 것만도 가능한 멤버와이즈 생성자
    let yoon1 = Student(name: "Xerath Yoon", location: "Pohang")
    
    // 모두 초기화하는 멤버와이즈 생성자
    // 이게 기본 멤버와이즈 생성자
    let yoon2 = Student(name: "Xerath Yoon", location: "Pohang", bestFriend: "Somebody")

     

    이런 식으로 초기화 안된 것만이 아니라 초기화가 된 것도 인자를 받아서 초기화하는 역할을 하잖아요.

    즉, 기본 멤버와이즈 생성자(모든 속성을 초기화해주는 생성자)가 보장이 되어야 하는데

    만약에 하나라도 private이면 이걸 바깥에서는 값을 바꿀 수 없으니 기본 멤버와이즈 생성자도 private이 되어야 하는 겁니다.

    그래서 이걸 변형한 멤버와이즈 생성자들도 모두 private이고요!

     

    그럼 과연 진짜 private이라도 멤버와이즈 생성자가 제공되는지 확인해보겠습니다!

    이렇게 struct 내부에서 쓰려고 하니까 멤버와이즈 생성자가 잘 제공되는 걸 확인할 수 있습니다.

     

    근데요...근데...!!!

    사실 이렇게 쓰기보단 우리는 외부에서 많이 쓰잖아요??!! 😭😭

    그래서 이때는 다음과 같이 생성자를 명시해서 쓰면 됩니다.

    struct Student {
        var name: String
        var location: String?
        private var bestFriend = "Nobody"
        
        init(name: String){
            self.name = name
        }
    }
    
    let yoon6 = Student(name: "Xerath Yoon")

     

    이건 private이 아니라 fileprivate이어도 마찬가지입니다!

     

    그리고 만약 public으로 속성을 갖고 있다면 public한 멤버와이즈 생성자를 만들어줘야 합니다.

    이럴 땐 다음처럼 해주면 됩니다!

    struct Student {
        public var name: String
        public var location: String?
        public var bestFriend = "Nobody"
        
        public init(name: String, location: String?, bestFriend: String) {
            self.name = name
            self.location = location
            self.bestFriend = bestFriend
        }
    }

     

    마무리

    이렇게 오늘은 멤버와이즈 생성자의 접근 지정자가 속성의 접근 지정자에 따라 바뀐다는 걸 깨닫게 되었습니다 ㅎㅎ

    생각보다 중요할 지도 모르는데 놓치고 갈 뻔해서 걱정했는데 다행입니다.

    이제서라도 확실히 알고 가게 되어서 휴~~~ ㅋㅋㅋㅋㅋㅋㅋ

    그럼 다음에도 좋은 포스팅으로 돌아오겠습니다! :-)

    참고

    https://docs.swift.org/swift-book/documentation/the-swift-programming-language/accesscontrol/#Default-Initializers:~:text=Default%20Memberwise%20Initializers,the%20type%E2%80%99s%20definition.

     

    Documentation

     

    docs.swift.org

    https://babbab2.tistory.com/167

     

    Swift) 초기화(Initializers) 이해하기 (1/6) - 구조체(Struct)의 초기화

    안녕하세요, 소들입니다! :) 제 포스팅의 시작은 Swift / iOS 기초를 깊게 다지자!! 였는데, 아직 다루고 싶은 글이 너무 많은데 언제부턴가 기초에 대해서는 안 썼더라구요 T.T 그래서 다시 Syntax 관

    babbab2.tistory.com

    https://icksw.tistory.com/118

     

    [Swift 문법] Swift 공식 문서 정리 - 26 - Access Control

    이번 글에서는 Swift 공식 문서의 26번째 단원인 Access Control을 읽고 정리한 글을 쓰려고 합니다. Swift 공식문서 26단원 - Access Control Access Control 접근 제어는 다른 소스 파일 및 모듈의 코드에서 현재

    icksw.tistory.com

     

     

     


    아직 꼬꼬마 개발자입니다.

    더 나은 설명이나 코드가 있다면 언제든 환영입니다.

    적극적인 조언과 피드백 부탁드립니다!

     

    그럼 오늘도 개발 가득한 하루되세요!

    - Xerath -

    🤖🤖🤖🤖🤖🤖🤖

     

    728x90
    반응형