티스토리 뷰

반응형

이번 글에서는 Swift 공식 문서의 26번째 단원인 Access Control을 읽고 정리한 글을 쓰려고 합니다.

 

Swift 공식문서 26단원 - Access Control

Access Control

접근 제어는 다른 소스 파일 및 모듈의 코드에서 현재 코드 부분에 대한 접근을 제한한다. 이 기능을 사용하면 코드의 구현 세부 정보를 숨기고 해당 코드에 접근하고 사용할 수 있는 기본 인터페이스를 지정할 수 있다.

 

특정 접근 수준을 개별 타입(클래스, 구조체, 열거형)과 해당 타입에 포함된 프로퍼티, 메서드, 생성자, 서브 스크립트에 할당할 수 있다. 프로토콜은 전역 상수, 전역 변수, 전역 함수와 마찬가지로 특정 컨텍스트로 제한될 수 있다.

 

다양한 수준의 접근 제어를 제공하는 것 외에도 Swift는 일반적인 시나리오에 대한 기본적인 접근 수준을 제공하여 명시적 접근 제어 수준을 지정해야하는 필요성을 줄여준다. 실제로 단일 대상 앱을 작성하는 경우 명시적으로 접근 제어 수준을 지정할 필요가 없다.

 

이 글에서는 접근 제어를 적용할 수 있는 코드의 다양한 측면(프로퍼티, 타입, 함수)을 "entities" (엔티티)라고 할 예정이다.


Modules and Source Files

Swift의 접근 제어 모델은 모듈 및 소스 파일의 개념을 기반으로 한다.

 

모듈은 단일 단위로 빌드 및 제공되며 Swift의 import 키워드를 사용하여 다른 모듈에서 가져올 수 있는 단일 코드 배포 단위인 프레임 워크, 애플리케이션이다.

 

Xcode의 각 빌드 대상은(App bundle, framework) Swift에서 별도의 모듈로 처리된다. 앱 코드의 여러 측면을 독립형 프레임 워크로 그룹화하면 해당 프레임 워크 내에서 정의한 모든 것은 앱에 가져와서 사용할 때 별도의 모듈에 속하게 된다. 이는 다른 프레임 워크에서 사용될 때도 마찬가지이다.

 

소스 파일은 모듈 내의 단일 Swift 소스 코드 파일이다. 개별 타입을 별도의 소스 파일에 저장하는 것이 일반적이지만 단일 소스 파일에 여러 타입, 함수 등에 대한 정의가 포함될 수 있다.


Access Levels

Swift는 코드 내의 엔티티에 대해 5가지 접근 수준을 제공한다. 이러한 접근 수준은 엔티티가 정의된 소스 파일, 소스 파일이 속한 모듈과 관련된다.

 

public 접근 및 open 접근을 사용하면 정의 모듈의 모든 소스 파일과 정의 모듈을 가져오는 다은 모듈의 소스 파일에서 엔티티를 사용할 수 있다. 일반적으로 프레임 워크에 대한 공용 인터페이스를 지정할 때 open, public 접근을 사용한다.

 

  • Internal 접근을 통해 엔티티를 정의 모듈의 모든 소스 파일 내에서 사용할 수 있지만 해당 모듈 외부의 소스 파일에서는 사용할 수 없다. 일반적으로 앱, 프레임 워크의 내부 구조를 정의할 때 내부 접근을 사용한다.
  • File-private 접근은 엔티티의 사용을 자체 정의 소스 파일로 제한한다. 즉 정의된 소스파일에서만 사용가능하다는 말이다. File-private 접근을 사용하여 특정 기능의 구현 세부 정보를 전체 파일 내에서 사용하는 경우 이를 숨길 수 있다.
  • Private 접근은 엔티티 사용을 둘러싸는 선언과 동일한 파일에 있는 해당 선언의 익스텐션으로 제한한다. 이러한 세부 정보가 단일 선언 내에서만 사용되는 경우 특정 기능 부분의 구현 세부 정보를 숨길 때 Private 접근을 사용하면 좋다.

Open 접근은 가장 제한이 적은 접근 수준이고 Private 접근은 제한이 가장 많은 접근 수준이다.

 

Open 접근은 클래스와 클래스 멤버에만 적용될 수 있으며 이글의 Subclassing 섹션에서 설명하는 것처럼 모듈 외부의 코드가 서브 클래스 및 재정의 할 수 있다는 점에서 Public 접근과는 다르다. 클래스를 open 접근으로 표시하면 해당 클래스를 슈퍼 클래스로 사용하는 다른 모듈의 코드가 미치는 영향을 고려하며 클래스의 코드를 설계했음을 나타낸다.

Guiding Principle of Access Levels

Swift의 접근 수준은 전반적인 지침 원칙을 따른다. 더 낮은 접근 수준을 가진 다른 엔티티와 관련해서 엔티티를 정의할 수는 없다. 예를 보며 이해해보자.

 

  • Public 변수는 internal, file-private, private 타입을 갖도록 정의할 수 없다. 다른 타입들은 Public 변수가 사용되는 모든 곳에서 사용 가능하지 않을 수 있기 때문이다.
  • 함수는 주변 코드에서 구성 유형을 사용할 수 없는 상황에서 함수를 사용할 수 있기 때문에 매개변수 타입 및 반환 타입 보다 더 높은 접근 수준을 가질 수는 없다.

언어의 다양한 측면에 대한 지침 원칙의 구체적인 의미는 잠시후에 자세히 알아보자.

Default Access Levels

코드의 모든 항목은 명시적 접근 수준을 직접 지정하지 않는 경우 기본적으로 internal로 접근 수준이 설정된다. 결과적으로 대부분의 경우 코드에 명시적으로 접근 수준을 지정할 필요가 없다.

Access Levels for Single-Target Apps

간단한 단일 대상 앱을 작성할 때 앱의 코드는 일반적으로 앱 내에 자체 포함되며 앱의 모듈 외부에서 사용할 수 있도록 만들 필요가 없다. 즉 접근 수준을 정하지 않아도 알아서 부여되는 internal 접근 수준이 이러한 요구사항을 만족시킨다. 따라서 굳이 접근 수준을 직접 설정할 필요가 없다. 하지만 앱 모듈 내의 다른 코드에서 구현 세부 정보를 숨기기 위해 코드의 일부를 file-private, private로 설정할 수 있다.

Access Levels for Frameworks

프레임 워크를 개발 할 때 프레임 워크를 가지고 오는 앱과 다른 모듈에서 보고 접근할 수 있도록 하는 프레임 워크에 대한 공용 인터페이스를 open, public 접근 수준으로 설정한다. 이 공용 인터페이스는 프레임 워크를 위한 애플리케이션 프로그래밍 인터페이스 혹은 API이다.

 

프레임 워크의 모든 내부 구현 정보는 여전히 internal 접근 수준을 사용할 수 있으며 프레임 워크 내부 코드의 다른 부분에서 숨기려는 경우 private, file-private로 설정할 수 있다. 프레임 워크의 API 일부가 되기를 원하는 경우에만 항목을 open, public으로 설정해한다.

Access Levels for Unit Test Targets

단위 테스트 대상이 있는 앱을 작성할 때 테스트하려면 앱의 코드를 해당 모듈에서 사용할 수 있어야 한다. 기본적으로 open, public으로 설정된 엔티티만 다른 모듈에 접근할 수 있다. 그러나 @testable 속성을 사용하여 제품 모듈에 대한 가져오기 선언을 표시하고 테스트를 활성화하여 해당 제품 모듈을 컴파일하는 경우 단위 테스트 대상은 모든 내부 엔티티에 접근할 수 있다.


Access Control Syntax

그럼 이제 접근 수준을 정의하는 방법을 알아보자. 엔티티 선언 시작 부분에 open, public, internal, fileprivate, private 중에 하나를 선택해서 배치하면 엔티티의 접근 수준을 정의할 수 있다.

public class SomePublicClass {}
internal class SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
private class SomePrivateClass {}

public var somePublicVariable = 0
internal let someInternalConstant = 0
fileprivate func someFilePrivateFunction() {}
private func somePrivateFunction() {}

 

물론 아까 위에서 말한대로 따로 접근 수준을 설정하지 않으면 internal 접근 수준으로 설정된다.

class SomeInternalClass {}              // implicitly internal
let someInternalConstant = 0            // implicitly internal

Custom Types

만약 접근 수준을 직접 지정하려면 타입을 정의할 때 지정해야 한다. 그런 뒤 만들어진 타입은 접근 수준에 맞게 사용할 수 있다. 예를 들어 file-private 클래스를 정의한 경우 해당 클래스는 file-private 클래스가 정의된 소스 파일에서 타입 프로퍼티, 함수 매개변수, 함수 반환 타입으로만 사용할 수 있다.

 

어떤 타입의 접근 제어 수준은 해당 타입의 멤버(프로퍼티, 메서드, 생성자, 서브스크립트)의 기본 접근 수준에도 영향을 준다. 접근 수준을 private, file-private로 정의한 경우 타입의 멤버들의 기본 접근 수준도 private, file-private가 된다. 하지만 만약 타입의 접근 수준을 public, internal로 정의한 경우 혹은 default로 internal로 정의한 경우도 모두 멤버들의 기본 접근 수준은 internal이 된다.

 

Public 타입의 멤버들은 기본적으로 public 접근 수준을 갖는 것이 아니라 internal을 갖는다. 이를 public으로 수정하려면 명시적으로 표시해줘야 한다. 이렇게 만들어 둬서 타입에 대한 공개 API가 public으로 옵트 인하는 항목인지 확인하고 실수로 타입의 내부 작동을 공개 API로 표시하지 않도록 해준다.

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
}

위의 코드와 같이 접근 수준을 사용자가 직접 정의할 수 있다.

 

Tuple Types

튜플 타입에 대한 접근 수준은 튜플에 속한 타입들의 접근 수준 중 가장 낮은 접근 수준으로 결정된다. 예를들어 internal 접근 수준이 있는 타입과 private 접근 수준이 있는 타입이 있고 이 두 개의 타입으로 튜플을 구성한다면 튜플의 접근 수준은 복합 접근 수준이 되어 private로 설정된다.

 

튜플 타입은 클래스, 구조체, 열거형, 함수와 같은 방식으로 독립형 정의가 없다. 따라서 튜플 타입의 접근 수준은 튜플의 구성요소에 의해 자동적으로 결정되며 튜플의 접근 수준을 명시적으로 지정할 수 없다.

 

Function Types

함수타입에 대한 접근 수준은 함수 매개변수, 반환 타입 중 가장 낮은 수준으로 결정된다. 이렇게 자동으로 설정된 접근 수준이 컨텍스트 기본값과 일치하지 않는 경우 함수 정의의 일부로 접근 수준을 명시적으로 지정해줘야 한다.

func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // function implementation goes here
}

위의 코드에서 정의된 함수는 따로 접근 수준을 정의하지 않았다. 따라서 기본적인 접근 수준인 internal로 설정될 것이라 예상할 수 있지만 그렇지 않다. 그 이유는 함수의 반환 타입이 튜플이며 이 튜플을 구성하는 타입들의 접근 수준 중 가장 낮은 것이 private이므로 이 함수는 이렇게 정의되면 안 된다.

private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // function implementation goes here
}

즉 위와 같이 함수를 private 접근 수준으로 명시적으로 표시해줘야 한다. 이유는 반환 타입이 private 접근수준을 가진 튜플이기 때문에 만약 함수가 public으로 설정되었고 public 수준을 가진 사용자가 이 함수를 사용했을 때 반환타입에대한 접근 권한이 없을 수 있기 때문이다. 따라서 함수의 접근 수준을 반환 타입, 매개변수의 접근 수준에 맞게 명시적으로 표시해줘야한다.

 

Enumeration Types

열거형의 case들은 그들이 속한 열거형과 동일한 접근 수준을 갖는다. 이 말은 case별로 다른 접근 수준을 지정할 수 없다는 말이다.

public enum CompassPoint {
    case north
    case south
    case east
    case west
}

따라서 위와 같이 public 접근 수준으로 정의된 CompassPoint열거형의 모든 케이스들은 public 접근 수준을 갖는다.

 

Raw Values and Associated Values

열거형에서 정의한 raw value, associated value에 사용되는 타입은 최소한 열거형의 접근 수준보다는 낮은 접근 수준을 가져야 한다. 예를 들어 열거형의 접근 수준이 internal이라면 raw value의 접근 수준으로 private를 사용할 수 없다. 당연한 말이지만 public은 가능하다.

 

Nested Types

중첩 타입의 접근 수준은 포함된 타입이 public이 아닌 경우 포함 타입과 동일하다. 아까 위에서 언급한 대로 public 타입으로 정의된 타입 안의 타입들은 기본적으로 internal 접근 수준을 갖는다. 물론 이를 명시적으로 표시하여 수정할 수 있다.


Subclassing

현재 접근 컨텍스트에서 접근할 수 있고 서브 클래스와 동일한 모듈에 정의된 모든 클래스를 서브 클래스로 지정할 수 있다. 다른 모듈에 정의된 모든 open 클래스를 서브 클래스로 지정할 수도 있다. 서브 클래스는 슈퍼 클래스보다 더 높은 접근 수준을 가질 수 없다. 예를 들어 슈퍼 클래스의 접근 수준이 internal 일 때 서브 클래스의 접근 수준으로 open, public으로 정의할 수 없다는 말이다.

 

또한 동일한 모듈에 정의된 클래스의 경우 특정 접근 컨텍스트에 표시되는 모든 클래스 멤버(메서드, 프로퍼티, 생성자, 서브 스크립트)를 override 할 수 있다. 다른 모듈에 정의된 클래스가 경우 open 수준의 멤버들에 대해서 override 할 수 있다.

 

Override는 상속된 클래스 멤버를 슈퍼 클래스 버전보다 더 쉽게 접근할 수 있도록 만들 수 있다. 예를 보며 이해해보자.

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

internal class B: A {
    override internal func someMethod() {}
}

위와 같이 A 클래스가 있고 이를 상속받은 B 클래스가 있다고 해보자. A에 있는 someMethod()는 file-private 접근 수준을 가지고 있다. 이를 B 클래스에서 override 할 땐 internal로 접근 수준을 바꿀 수 있다는 말이다.

 

슈퍼 클래스의 멤버에 대한 호출이 허용된 접근 수준 컨텍스트에서 발생하는 서브 클래스 멤버가 접근 권한이 낮은 슈퍼 클래스의 멤버를 호출하는 것도 가능하다. 아래 예를 보며 이해해보자.

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

internal class B: A {
    override internal func someMethod() {
        super.someMethod()
    }
}

위의 코드를 보면 A 클래스의 file-private로 정의된 someMethod()를 B 클래스의 internal로 정의된 someMethod()에서 호출한 것을 볼 수 있다. 이 둘은 동일한 소스 파일에 정의되어 있기 때문에 위와 같은 행위가 가능한 것이다.


Constants, Variables, Properties, and Subscripts

상수, 변수, 프로퍼티는 타입의 접근 수준보다 더 높을 수는 없다. 아래 예제를 보며 이해해 보자.

private var privateInstance = SomePrivateClass()

위와 같이 타입을 정의해야 한다는 말이다. 즉 privateInstance를 public과 같이 SomePrivateClass보다 더 높은 접근 수준으로 정의할 수 없다. 동일한 이유로 서브 스크립트도 인덱스 타입이나 반환 타입보다 접근 수준이 더 높을 수 없다.

Getters and Setters

상수, 변수, 프로퍼티, 서브 스크립트에 대한 getter, setter는 이들이 속한 상수, 변수, 프로퍼티, 서브 스크립트와 동일한 접근 수준을 자동으로 받는다.

 

Setter의 접근 수준을 getter보다 낮게 설정하여 읽기-쓰기 범위를 제한할 수도 있다. var, subscript 키워드 앞에 fileprivate(set), private(set), internal(set)을 작성하여 더 낮은 접근 수준을 할당하면 된다.

struct TrackedString {
    private(set) var numberOfEdits = 0
    var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
}

위의 코드에서는 문자열 타입이 수정된 횟수를 추적하는 TrackedString이라는 구조체를 정의했다. 이 구조체는 초기 값이 ""인 value라는 저장 프로퍼티를 정의한다. 또한 value 프로퍼티가 수정된 횟수를 추적하는 numberOfEdits라는 저장 프로퍼티도 정의한다. 추적은 didSet으로 구현되고 value가 새로운 값으로 설정될 때 numberOfEdits가 증가한다.

 

위의 코드에서 구현된 TrackedString, value는 모두 접근 수준을 명시적으로 제공하지 않았기 때문에 기본적으로 internal 접근 수준을 갖는다. 하지만 numberOfEditsprivate(set)으로 표시되어 프로퍼티의 getter는 internal 수준이지만 setter는 private 수준임을 알 수 있다. 따라서 TrackedString 구조체 내부에서만 수정 가능하며 외부에서는 읽기 전용 프로퍼티로 표시된다.

var stringToEdit = TrackedString()
stringToEdit.value = "This string will be tracked."
stringToEdit.value += " This edit will increment numberOfEdits."
stringToEdit.value += " So will this one."
print("The number of edits is \(stringToEdit.numberOfEdits)")
// Prints "The number of edits is 3"

위와 같이 TrackedString 구조체의 인스턴스를 만들어보면 이를 이해할 수 있다. 위와 같이 외부에서 numberOfEdits 프로퍼티의 현재 값을 쿼리 할 수 있지만 수정할 수는 없다.

 

만약 getter에도 명시적으로 접근 수준을 할당하고 싶다면 아래와 같이 만들어주면 된다.

public struct TrackedString {
    public private(set) var numberOfEdits = 0
    public var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
    public init() {}
}

위의 코드는 접근 수준이 public으로 정의된 TrackedString 구조체이다. 따라서 구조체의 구성원들은 모두 기본적으로 internal 접근 수준을 갖는다. 하지만 위와 같이 구성원들의 접근 수준을 수정할 수 있다. 만약 위와 같은 구조체에서 setter를 private로 만들고 싶다면 위에 나온 대로 public private(set)으로 만들어주면 된다.


Initializers

사용자 정의 생성자에는 초기화하는 타입보다 낮거나 같은 접근 수준을 할당할 수 있다. 유일한 예외는 required 생성자이다. required 생성자는 자신이 속한 클래스와 동일한 접근 수준을 가져야 만한다.

 

함수 및 메서드 매개변수와 마찬가지로 생성자의 매개변수 타입은 생성자 자체 접근 수준보다 더 낮을 수 없다.

Default Initializers

Swift는 모든 프로퍼티에 대한 기본값을 제공하고 하나 이상의 생성자를 제공하지 않는 구조체, 클래스에 대하여 Default 생성자는를 자동으로 제공한다.

 

Default 생성자는 해당 타입이 public으로 정의되지 않는 한 초기화하는 타입과 동일한 접근 수준을 갖는다. public으로 정의된 경우 default 생성자는 internal로 접근 수준이 설정된다. 다른 모듈에서 사용할 때 인수 없는 생성자로 공용 형식을 초기화하려면 타입 정의의 일부로 생성자를 public로 명시적으로 표시해줘야 한다.

Default Memberwise Initializers for Structure Types

구조체 타입에 대한 default memberwise 생성자는 구조체의 저장 프로퍼티 중 하나라도 private인 경우 private로 접근 수준이 설정된다. 마찬가지로 구조체의 저장 프로퍼티가 file-private인 경우 생성자도 file-private이다.

 

아까 본 default 생성자와 마찬가지로 다른 모듈에서 public 구조체를 memberwise 생성자로 초기화하려면 타입 정의의 일부로 public memberwise 생성자를 직접 제공해야 한다.


Protocols

프로토콜 타입에 명시적으로 접근 수준을 할당하려면 프로토콜을 정의하는 지점에서 정의해야 한다. 이를 통해 특정 접근 컨텍스트 내에서만 채택할 수 있는 프로토콜을 만들 수 있다.

 

프로토콜 정의 안의 각 요구사항의 접근 수준은 프로토콜과 동일한 접근 수준으로 자동 설정된다. 이를 다른 접근 수준으로 설정할 수는 없으며 이렇게 해서 프로토콜을 채택하는 모든 타입에서 프로토콜의 모든 요구사항을 볼 수 있다.

 

public 수준의 프로토콜을 정의하는 경우 프로토콜의 요구 사항이 구현될 때 public 접근 수준이 필요하다. 이는 지금까지 public으로 설정한 것들의 내부 요소들이 자동으로 internal로 설정되던 것들과는 다르다.

 

Protocol Inheritance

기존 프로토콜에서 상속하는 새로운 프로코톨을 정의하는 경우 새로운 프로토콜은 상속된 프로토콜과 최대 동일한 접근 수준을 가질 수 있다. 예를 들어 internal 프로토콜에서 상속된 public 프로토콜을 작성할 수는 없다.

 

Protocol Conformance

타입은 타입 자체보다 접근 수준이 낮은 프로토콜을 준수할 수 있다. 예를 들어 다른 모듈에서 사용할 수 있지만 internal 프로토콜에 대한 적합성은 internal 프로토콜의 정의 모듈 내에서만 사용할 수 있는 public 타입을 정의할 수 있다.

 

타입이 특정 프로토콜을 따르는 컨텍스트는 타입의 접근 수준과 프로토콜의 접근 수준의 최솟값이다. 예를 들어 타입이 public이지만 준수하는 프로토콜이 internal인 경우 해당 프로토콜에 대한 타입의 준수도 internal이다.

 

프로토콜을 준수하기 위해 타입을 작성하거나 익스텐션 할 때 각 프로토콜의 요구사항의 타입 구현이 해당 프로토콜에 대한 타입의 준수와 최소한 동일한 접근 수준을 가지고 있는지 확인 해야한다. 예를 들어 public 타입이 internal 프로토콜을 준수하는 경우 각 프로토콜 요구사항 타입 구현은 최소한 internal 이어야 한다.

 

Swift의 프로토콜 준수는 전역적이므로 동일한 프로그램 내에서 어떤 타입이 2개의 다른 방식으로 프로토콜을 준수하는 것은 불가능하다.


Extensions

클래스, 구조체, 열거형을 사용할 수 있는 모든 컨텍스트에서 클래스, 구조체, 열거형을 익스텐션 할 수 있다. 익스텐션에 추가된 모든 타입 멤버는 익스텐션 중인 원래 타입에 선언된 타입 멤버와 동일한 접근 수준을 갖는다. public, internal 타입을 익스텐션 하는 경우 추가하는 모든 새로운 타입 멤버는 기본 접근 수준이 internal이다. file-private 타입을 익스텐션 하는 경우 추가하는 모든 새 타입 멤버는 file-private 접근 수준을 갖는다. private도 마찬가지이다.

 

명시적으로 접근 수준 수정자를 표시하여 익스텐션 할 때 추가되는 모든 멤버들에게 기본으로 부여되는 접근 수준을 수정할 수 있다. 이러한 기본값은 개별 타입 멤버의 익스텐션 내에서 계속 재정의 할 수 있다.

 

익스텐션을 사용하여 프로토콜 준수를 추가하는 경우 익스텐션에 대한 접근 수준 수정자를 명시적으로 제공할 수 없다. 대신 프로토콜의 자체 접근 기준을 사용하여 익스텐션 내의 각 프로토콜 요구사항 구현에 대한 기존 접근 수준을 제공한다.

Private Member in Extensions

익스텐션 하려는 클래스, 구조체, 열거형과 동일한 파일에 있는 익스텐션은 익스텐션의 코드가 원래 타입 선언의 일부로 작성된 것처럼 작동한다. 결과적으로는 다음 3가지를 수행할 수 있다.

 

  • 원래 선언에서 private 멤버를 선언하고 동일한 파일의 익스텐션에서 해당 멤버에 접근 한다.
  • 한 익스텐션에서 private 멤버를 선언하고 동일한 파일의 다른 익스텐션에서 해당 멤버에 접근한다.
  • 익스텐션에서 private 멤버를 선언하고 동일한 파일의 원래 선언에서 해당 멤버에 접근 한다.

이 동작은 타입에 private 항목이 있는지 여부에 관계없이 동일한 방식으로 익스텐션을 사용하여 코드를 구성할 수 있음을 의미한다. 예를 들어 다음과 같은 간단한 프로토콜이 있다고 해보자.

protocol SomeProtocol {
    func doSomething()
}

이 프로토콜을 준수하는 구조체를 만들어보면..

struct SomeStruct {
    private var privateVariable = 12
}

extension SomeStruct: SomeProtocol {
    func doSomething() {
        print(privateVariable)
    }
}

위와 같이 익스텐션을 사용하여 프로토콜을 준수하는 구조체를 만들 수 있다.


Generics

제네릭 타입, 제네릭 함수에 대한 접근 수준은 제네릭 타입, 함수 자체의 접근 수준과 해당 타입 매개변수에 대한 모든 제약 조건의 접근 수준 중 가장 낮은 것이 된다.


Type Aliases

정의한 모든 타입 alias는 접근 제어를 위해 구별 타입으로 처리된다. 타입 alias는 지정된 타입의 접근 수준보다 낮거나 같은 접근 수준을 가질 수 있다. 예를 들어 private 타입 alias는 private, file-private, internal, public, open 타입의 alias를 지정할 수 있다. 하지만 public 타입 alias는 internal, file-private, private 타입의 alias를 지정할 수 없다.

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함