[Swift] 접근 제어

팔랑이·2023년 6월 15일
post-thumbnail

Swift가 제공하는 5가지 접근 제어 단계 형식을 통해 다른 소스파일 및 모듈에서의 접근을 제한할 수 있다. 본 게시글 내에서 함수, 메소드, 프로퍼티, 이니셜라이저 등을 간결하게 엔티티라고 표현할 것임.

접근 레벨 (밑으로 갈수록 접근 레벨이 낮아진다고 표현)

  • open: 외부 모듈에서도 접근 가능, 서브클래싱 및 오버라이딩 가능
  • public: 외부 모듈에서 접근 가능. 단, 서브클래싱 및 오버라이딩 불가능
  • internal: 외부 모듈에서 접근 불가능, 해당 모듈의 모든 소스에서 접근 가능. 접근 단계 디폴트값.
  • file-private: 특정 엔티티 선언한 파일 안에서만 접근 가능
  • private: 해당 엔티티를 선언한 괄호{} 안에서만 접근 가능

👉🏻 모듈-> 하나의 앱 단위, 소스파일-> xcode프로젝트 안의 한 파일

일반적인 특징

  • 접근 레벨이 더 낮은 단계의 엔티티 안에서 높은 단계의 엔티티가 정의될 수 없음. 이론상 정의된다고 해도 낮은 단계의 엔티티의 수준을 넘어 사용될 수 없기 때문.

  • 같거나 낮은 단계는 사용 가능. 디폴트는 internal.
    다음과 같이 사용 가능하다.

public class SomePublicClass {                  // explicitly public class
    public var somePublicProperty = 0            // explicitly public class member
    var someInternalProperty = 0                 // implicitly internal class member
    fileprivate func someFilePrivateMethod() {}  // explicitly file-private class member
    private func somePrivateMethod() {}          // explicitly private class member
}


class SomeInternalClass {                       // implicitly internal class
    var someInternalProperty = 0                 // implicitly internal class member
    fileprivate func someFilePrivateMethod() {}  // explicitly file-private class member
    private func somePrivateMethod() {}          // explicitly private class member
}


fileprivate class SomeFilePrivateClass {        // explicitly file-private class
    func someFilePrivateMethod() {}              // implicitly file-private class member
    private func somePrivateMethod() {}          // explicitly private class member
}


private class SomePrivateClass {                // explicitly private class
    func somePrivateMethod() {}                  // implicitly private class member
}

튜플 타입

  • 튜플 안에 다른 접근제어 레벨 엔티티가 존재하면, 더 낮은 단계로 제어단계가 설정됨
  • ex) private과 internal 단계가 둘 다 있는 튜플 -> private으로 설정

함수 타입

  • 어떤 함수의 매개변수가 각각 다른 접근제어 레벨이면 더 낮은 단계로 설정해야 함. 이를 함수 앞에도 명시해줘야 컴파일 오류가 안 남.
func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // 이러면 컴파일 오류
}

private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // 이렇게 함수 앞에도 선언해줘야 오류 X
}

서브클래싱

서브클래스는 슈퍼클래스보다 높은 단계의 접근제어 레벨을 설정할 수 없다. 그러나 다음과 같이 오버라이딩 하면 가능.

public class A {
    fileprivate func someMethod() {}
}

internal class B: A {
    override internal func someMethod() {}
    super.someMethod() //이렇게 설정할 수 있기 때문에 사용 가능
}

게터, 세터의 접근레벨 설정

게터와 세터는 기본적으로 변수나 상수, 프로퍼티와 같은 수준의 접근단계를 가진다. 이보다 더 낮게는 설정 가능.

struct TrackedString {
    private(set) var numberOfEdits = 0 //다음과 같이 더 낮은 단계의 접근레벨과 (set), (get) 등을 붙여줌
    var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
}

위 예제에서, private(set)이 없었다면 numberOfEdits가 모듈 밖에서도 사용이 가능했을 것(default->internal). 그러나 private(set)으로 설정해줬기 때문에 TrackedString 안에서만 접근 가능해졌다.



이후 내용은 제네릭 등 더 공부하고 나서 추가.

🌏 참고사이트
Swift Language Guide

profile
정체되지 않는 성장

0개의 댓글