[iOS 2주차] 문제 해결: public 설정에 따른 명시적 initializer 필요

DoyleHWorks·2024년 10월 29일
1
post-thumbnail

문제

Calculator 개인 과제를 진행하면서, public 접근 제한자 (class의 경우 open도 가능) 를 이용해 클래스를 외부 파일로 변환하여 작성할 수 있음을 알았다. 그런데 class 앞에도 public을 붙였고, 안에 있는 func 앞에도 public을 잘 붙였는데, 어째선지 오류가 떴다.

문제 접근

error: Calculator.playground:10:24: 'AddOperation' initializer is inaccessible due to 'internal' protection level
  let addOperation = AddOperation()

Calculator_Sources.AddOperation (internal):4:14: note: 'init()' declared here
  internal init()

오류를 읽어보니, internal 보호 수준 때문에 initializer에 접근을 못한다고 한다.
근데... 그 클래스에 초기화(initialize)를 할 프로퍼티가 없다. 초기화할 프로퍼티가 없는데 어째서 초기화 오류가?? 일단 검색해봤다.

Google 검색: initializer is inaccessible due to 'internal' protection level when there is no property

곤란하게도 여기서 나온 검색 결과의 경우 when there is no property 라고 적었음에도 대부분 프로퍼티가 있는 경우였다. 하나씩 들어가봤는데, 결국 내가 원하는 답은 없고 작성자의 접근 제한자 입력 실수가 대부분이었다. 구글 검색을 포기하고 ChatGPT한테 물어보러.. 가기 전에, 그냥 순수하게 에러 메세지만 적어보기로 했다.

Google 검색: initializer is inaccessible due to 'internal' protection level
!

그냥 비슷한 검색결과가 나왔는데, 최상단에 뜬 글(2016. 11. 29.)을 눌러보았다.

stack overflow: Initializer is inaccessable due to 'internal' protection level

이것도 결국 비슷한 내용인 것 같은데.. 그래도 달린 답변을 한 번 볼까?

상당히 추천을 많이 받은 답변과 Swift를 욕하는 댓글...!

해결 방안

public init() {}

As long as you do not implement init() explicitly, it is marked as internal by default. You need to overwrite that permission level to be able to instantiate from outside your framework.

init()을 명시적으로 적용해주지 않는 한, 기본값으로 internal 설정이 된다고 한다. 속는 셈 치고 분리시킨 클래스들에게 전부 public init() {}를 넣어줬더니, 정상적으로 작동하였다.

정상 작동 확인

인사이트

관련 내용을 좀 더 찾아보니, Swift는 클래스나 구조체에 프로퍼티가 없을 때 자동으로 기본 생성자(internal init())를 생성한다고 한다. 근데 어라? 자동으로 기본 생성자를 제공하는 건 구조체(struct)의 memberwise initializer만이라고 배운 것 같은데... 클래스(class)도 알고보니 짜잔, 기본 생성자를 제공한다고 한다. 클래스의 접근 수준이 public 또는 open인 경우, Swift는 자동으로 생성자를 internal 수준으로 제공한다. (어째서...) 왜 굳이 그렇게 하는지 이해는 안되지만, 클래스 특유의 상속 개념 등 때문에 그런게 아닐까 추측된다. (현재로선 여기서 더 파고들고 싶지 않다)
※ 어쩌면 헷갈릴수도 있는 부분: 클래스의 기본 생성자는 구조체의 convenience initializer가 작동하는 방식과는 다르게 생성된다 (class vs struct)


오늘의 Pull Request & 느낀 점

예외처리 기능을 추가하면서 throw랑 예외처리용 클래스? 도 써보고 싶었는데 당장은 감이 안 오고 예외 경우가 너무 적은 것 같아서, 그냥 if문으로 처리했다. .nan 개념도 처음 배웠다. Not a Number를 의미한다. 숫자 타입의 nil 같은 느낌일까? 물론 쓰임새는 다르겠지만..
코드는 다시 보면 볼수록 정제할 부분이 보이는 게 상당히 매력적인 것 같다. 오늘은 REFACTOR 커밋을 특히 많이 했다. 볼 때마다 수정할 곳이 보인다는 건 글쓰기 마냥 마무리 짓기가 애매하다는 것... 그 과정에서 개발자의 성격이 드러나는 것 같다. 알고리즘 문제를 푸는 여러 사람들의 답안도 개성이 넘친다. 그렇게 생각하니, 자신이 쓴 코드란 건 애착이 갈 수 밖에 없는 것 같다.

profile
Reciprocity lies in knowing enough

3개의 댓글

comment-user-thumbnail
2024년 10월 30일

재밌게 읽었습니다🙂 구글링 방식이 저랑 거의 똑같으셔서 엄청 공감하면서 읽었어요! 저도 영어로 제가 겪는 문제를 쳐서 찾고(구체적인 상황 붙이는 거까지), 오류 메시지를 복붙하기도 하는데.. 스택오버플로우 화면도 그렇고 과정이 너무 친근해요 ㅋㅋㅋㅋ 근데 저는 사실 public 접근제한자 쓰임새가 잘 이해 안되는데, "클래스를 외부 파일로 변환하여 작성" 하면 뭐가 가능하고, 뭐가 좋은 건가요?

1개의 답글