접근자는 다른 소스 파일 및 모듈의 코드에서 코드 일부에 대한 액세스를 제한합니다. 이 기능을 사용하면 코드의 구현 세부 정보를 숨기고 해당 코드에 액세스하고 사용할 수있는 기본 인터페이스를 지정할 수 있습니다.
특정 액세스 수준을 개별 유형 (클래스, 구조체 및 열거형)과 해당 유형에 속하는 프로퍼티, 메서드, 이니셜 라이저 및 첨자에 할당 할 수 있습니다. 프로토콜은 전역 상수, 변수 및 함수와 마찬가지로 특정 컨텍스트로 제한 될 수 있습니다.
다양한 수준의 접근자를 제공하는 것 외에도 Swift는 일반적인 시나리오에 대한 기본 액세스 수준을 제공하여 명시 적 액세스 제어 수준을 지정할 필요성을 줄여줍니다. 실제로 단일 대상 앱을 작성하는 경우 명시적인 액세스 제어 수준을 전혀 지정할 필요가 없습니다.
NOTE
접근자를 적용 할 수 있는 코드의 다양한 측면 (속성, 유형, 함수 등)은 간결성을 위해 아래 섹션에서 “엔터티”라고합니다.
Modules and Source Files
모듈 및 소스 파일
Swift의 접근자 모델은 모듈 및 소스 파일의 개념을 기반으로합니다.
모듈은 단일 단위로 빌드 및 제공되며 Swift의 import 키워드를 사용하여 다른 모듈에서 가져올 수있는 프레임 워크 또는 애플리케이션 인 단일 코드 배포 단위입니다.
Xcode의 각 빌드 대상 (예 : 앱 번들 또는 프레임 워크)은 Swift에서 별도의 모듈로 처리됩니다. 앱 코드의 여러 측면을 독립형 프레임 워크로 그룹화하면 (아마도 여러 애플리케이션에서 해당 코드를 캡슐화하고 재사용하기 위해) 해당 프레임 워크 내에서 정의한 모든 것은 앱 내에서 가져 와서 사용하거나 다른 프레임 워크 내에서 사용될 때 별도의 모듈에 속하게됩니다.
소스 파일은 모듈 내의 단일 Swift 소스 코드 파일입니다 (실제로 앱 또는 프레임 워크 내의 단일 파일). 개별 유형을 별도의 소스 파일에 정의하는 것이 일반적이지만 단일 소스 파일에 여러 유형, 함수 등에 대한 정의가 포함될 수 있습니다.
Access Levels
접근 레벨
Swift는 코드 내의 엔터티에 대해 5 가지 액세스 수준을 제공합니다. 이러한 액세스 수준은 엔티티가 정의 된 소스 파일과 관련이 있으며 소스 파일이 속한 모듈과 관련이 있습니다.
- Open 엑세스 및 public 액세스를 통해 엔티티는 정의 모듈의 모든 소스 파일과 정의 모듈을 가져 오는 다른 모듈의 소스 파일에서 사용할 수 있습니다. 일반적으로 프레임 워크에 대한 공용 인터페이스를 지정할 때 Open 또는 public 액세스를 사용합니다. Open 액세스와 public 액세스의 차이점은 아래에 설명되어 있습니다.
- Internal 액세스를 통해 엔티티를 정의 모듈의 모든 소스 파일 내에서 사용할 수 있지만 해당 모듈 외부의 소스 파일에서는 사용할 수 없습니다. 일반적으로 앱 또는 프레임 워크의 내부 구조를 정의 할 때 Internal 액세스를 사용합니다.
- File-private 액세스는 엔티티의 사용을 자체 정의 소스 파일로 제한합니다. File-private 액세스를 사용하여 특정 기능의 구현 세부 정보를 전체 파일 내에서 사용하는 경우 이를 숨 깁니다.
- Private 액세스는 엔터티의 사용을 둘러싸는 선언과 동일한 파일에있는 해당 선언의 확장으로 제한합니다. 이러한 세부 정보가 단일 선언 내에서만 사용되는 경우 특정 기능 부분의 구현 세부 정보를 숨기려면 Private 액세스를 사용하면 됩니다.
Open 액세스는 가장 높은 (최소 제한) 액세스 수준이고 private 액세스는 가장 낮은 (가장 제한적인) 액세스 수준입니다.
Open 액세스는 클래스와 클래스 멤버에만 적용되며, 아래 서브 클래싱에서 설명하는 것처럼 모듈 외부의 코드가 서브 클래스 및 재정의 할 수 있다는 점에서 public 액세스와 다릅니다. 클래스를 open으로 표시하면 해당 클래스를 수퍼 클래스로 사용하는 다른 모듈의 코드가 미치는 영향을 고려했으며 그에 따라 클래스 코드를 설계했음을 나타냅니다.
Guiding Principle of Access Levels
엑세스 레벨의 기본 원칙
Swift의 액세스 수준은 전반적인 지침 원칙을 따릅니다. 더 낮은 (더 제한적인) 액세스 수준을 가진 다른 엔티티의 관점에서 엔티티를 정의 할 수 없습니다.
예를 들면 :
- 공용 변수가 사용되는 모든 곳에서 해당 유형을 사용하지 못할 수 있으므로 공용 변수는 내부, 파일 전용 또는 전용 유형을 갖는 것으로 정의 할 수 없습니다.
- 함수는 주변 코드에서 구성 유형을 사용할 수 없는 상황에서 함수를 사용할 수 있으므로 매개 변수 유형 및 반환 유형보다 더 높은 액세스 수준을 가질 수 없습니다.
언어의 다양한 측면에 대한이 지침 원칙의 구체적인 의미는 아래에서 자세히 설명합니다.
Default Access Levels
기본 접근수준
코드의 모든 항목 (이 장의 뒷부분에서 설명하는 몇 가지 특정 예외 포함)은 명시 적 액세스 수준을 직접 지정하지 않는 경우 기본 액세스 수준이(internal) 됩니다. 따라서 대부분의 경우 코드에 명시 적 액세스 수준을 지정할 필요가 없습니다.
Access Levels for Single-Target Apps
단일 대상 앱에 대한 액세스 수준
간단한 단일 대상 앱을 작성할 때 앱의 코드는 일반적으로 앱 내에 자체 포함되며 앱의 모듈 외부에서 사용할 수 있도록 만들 필요가 없습니다. 내부의 기본 액세스 수준은 이미 이 요구 사항과 일치합니다. 따라서 사용자 지정 액세스 수준을 지정할 필요가 없습니다. 그러나 앱 모듈 내의 다른 코드에서 구현 세부 정보를 숨기기 위해 코드의 일부를 file private 또는 private로 표시 할 수 있습니다.
Access Levels for Frameworks
프레임 워크에 대한 액세스 수준
프레임 워크를 개발할 때 프레임 워크를 가져 오는 앱과 같은 다른 모듈에서 보고 액세스 할 수 있도록 해당 프레임 워크에 대한 공개 인터페이스를 open 또는 public으로 표시합니다. 이 공용 인터페이스는 프레임 워크 용 애플리케이션 프로그래밍 인터페이스 (또는 API)입니다.
NOTE
프레임 워크의 모든 내부 구현 세부 정보는 여전히 내부의 기본 액세스 수준을 사용할 수 있으며, 프레임 워크 내부 코드의 다른 부분에서 숨기려는 경우 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입니다. 즉, SomeInternalClass 및 someInternalConstant는 명시적인 액세스 수준 수정자 없이 작성 될 수 있으며 여전히 internal 액세스 수준을 갖습니다.
class SomeInternalClass {} // 암시적 internal
let someInternalConstant = 0 // 암시적 internal
Custom Types
사용자 유형
사용자 지정 유형에 대한 명시 적 액세스 수준을 지정하려면 유형을 정의 할 때 지정합니다. 그런 다음 액세스 수준이 허용하는 모든 곳에서 새 유형을 사용할 수 있습니다. 예를 들어, file-private 클래스를 정의하는 경우 해당 클래스는 파일 전용 클래스가 정의 된 소스 파일에서 속성의 유형 또는 함수 매개 변수 또는 반환 유형으로 만 사용할 수 있습니다.
타입의 액세스 제어 수준은 해당 유형의 멤버 (속성, 메서드, 이니셜 라이저 및 아래 첨자)의 기본 액세스 수준에도 영향을줍니다. 타입의 액세스 수준을 private 또는 file private로 정의하는 경우 해당 구성원의 기본 액세스 수준도 private 또는 file private가됩니다. 타입의 액세스 수준을 internal 또는 public로 정의하는 경우 (또는 액세스 수준을 명시 적으로 지정하지 않고 기본 액세스 수준을 내부로 사용) 유형 구성원의 기본 액세스 수준은 내부(internal)가됩니다.
NOTE
public 유형은 기본적으로 public 멤버가 아닌 internal 멤버를 갖습니다. 형식 멤버를 공개하려면 명시 적으로 표시해야합니다. 이 요구 사항은 유형에 대한 공개 API가 공개에 옵트 인하는 항목인지 확인하고 실수로 유형의 내부 작동을 공개 API로 표시하지 않도록합니다.
public class SomePublicClass {// 명시 적으로 public 클래스
public var somePublicProperty = 0 // 명시 적으로 public 클래스 멤버
var someInternalProperty = 0 // 암시 적으로 internal 클래스 멤버
fileprivate func someFilePrivateMethod () {} // 명시 적으로 file private 클래스 멤버
private func somePrivateMethod () {} // 명시 적으로 private 클래스 멤버
}
class SomeInternalClass {// 암시 적으로 내부 클래스
var someInternalProperty = 0 // 암시 적으로 internal 클래스 멤버
fileprivate func someFilePrivateMethod () {} // 명시 적으로 file private 클래스 멤버
private func somePrivateMethod () {} // 명시 적으로 private 클래스 멤버
}
fileprivate class SomeFilePrivateClass {// 명시 적으로 file private 클래스
func someFilePrivateMethod () {} // 암시 적으로 file private 클래스 멤버
private func somePrivateMethod () {} // 명시 적으로 private 클래스 멤버
}
private class SomePrivateClass {// 명시 적으로 private 클래스
func somePrivateMethod () {} // 암시 적으로 private 클래스 멤버
}
Tuple Types
튜플 타입
튜플 타입에 대한 액세스 수준은 해당 튜플에서 사용되는 모든 타입 중 가장 제한적인 액세스 수준입니다. 예를 들어, internal 액세스가 있는 타입과 private 액세스가 있는 타입의 두 가지 타입에서 튜플을 구성하는 경우 해당 복합 튜플 유형의 액세스 수준은 private 이됩니다.
NOTE
튜플 타입에는 클래스, 구조체, 열거형 및 함수와 같은 방식으로 독립형 정의가 없습니다. 튜플 유형의 액세스 수준은 튜플 유형을 구성하는 유형에서 자동으로 결정되며 명시 적으로 지정할 수 없습니다.
Function Types
함수 타입
함수 타입에 대한 액세스 수준은 함수의 매개 변수 유형 및 반환 유형 중 가장 제한적인 액세스 수준으로 계산됩니다. 함수의 계산 된 액세스 수준이 컨텍스트 기본값과 일치하지 않는 경우 함수 정의의 일부로 액세스 수준을 명시 적으로 지정해야합니다.
아래 예제는 함수 자체에 대한 특정 액세스 수준 수정자를 제공하지 않고 someFunction ()이라는 전역 함수를 정의합니다. 이 함수가 “internal”의 기본 액세스 수준을 가질 것으로 예상 할 수 있지만 그렇지 않습니다. 실제로 someFunction ()은 아래와 같이 컴파일되지 않습니다.
func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// 함수 구현은 여기에
}
함수의 반환 유형은 위에서 사용자 정의 유형에 정의 된 두 개의 사용자 정의 클래스로 구성된 튜플 유형입니다. 이러한 클래스 중 하나는 internal 클래스로 정의되고 다른 클래스는 private 클래스로 정의됩니다. 따라서 복합 튜플 유형의 전체 액세스 수준은 private입니다 (튜플 구성 유형의 최소 액세스 수준).
함수의 반환 유형이 private이므로 함수 선언이 유효하려면 private 한정자로 함수의 전체 액세스 수준을 표시해야합니다.
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// function implementation goes here
}
public 또는 internal 한정자로 someFunction () 정의를 표시하거나 internal의 기본 설정을 사용하는 것은 유효하지 않습니다. 함수의 public 또는 internal 사용자가 함수의 반환 유형에 사용 된 private 클래스에 대한 적절한 액세스 권한이 없을 수 있기 때문입니다. .
Enumeration Types
열거형 타입
열거형의 개별 사례는 그들이 속한 열거와 동일한 액세스 수준을 자동으로받습니다. 개별 열거형 사례에 대해 다른 액세스 수준을 지정할 수 없습니다.
아래 예에서 CompassPoint 열거 형에는 public의 명시 적 액세스 수준이 있습니다. 따라서 north
, south
, east
, 및 west
열거형 사례에는 public 액세스 수준도 있습니다.
public enum CompassPoint {
case north
case south
case east
case west
}
Raw Values and Associated Values
원시값 및 관련값
열거형 정의의 모든 원시 값 또는 관련 값에 사용되는 유형은 적어도 열거형의 액세스 수준보다 높은 액세스 수준을 가져야합니다. 예를 들어 internal 액세스 수준이있는 열거형의 원시 값 유형으로 private 유형을 사용할 수 없습니다.
Nested Types
중첩 유형
중첩 유형의 액세스 수준은 포함 유형이 public이 아닌 경우 포함 유형과 동일합니다. public 유형 내에 정의 된 중첩 유형은 내부의 자동 액세스 수준을 갖습니다. public 유형 내의 중첩 유형을 공개적으로 사용할 수 있도록하려면 중첩 유형을 public으로 명시 적으로 선언해야합니다.
Subclassing
서브클래싱
현재 액세스 컨텍스트에서 액세스 할 수 있고 하위 클래스와 동일한 모듈에 정의 된 모든 클래스를 하위 클래스로 지정할 수 있습니다. 다른 모듈에 정의 된 모든 open 클래스를 하위 클래스로 지정할 수도 있습니다. 하위 클래스는 상위 클래스보다 더 높은 액세스 수준을 가질 수 없습니다. 예를 들어 internal 상위 클래스의 public 하위 클래스를 작성할 수 없습니다.
또한 동일한 모듈에 정의 된 클래스의 경우 특정 액세스 컨텍스트에 표시되는 모든 클래스 멤버 (method, property, initializer, or subscript)를 재정의 할 수 있습니다. 다른 모듈에 정의 된 클래스의 경우 모든 open 클래스 멤버를 재정의 할 수 있습니다.
재정의는 상속 된 클래스 멤버를 수퍼 클래스 버전보다 더 쉽게 액세스 할 수 있도록 할 수 있습니다. 아래 예제에서 클래스 A는 someMethod ()라는 file-private 메서드가 있는 public 클래스입니다. 클래스 B는 A의 하위 클래스이며 “internal”액세스 수준이 줄어 듭니다. 그럼에도 불구하고 클래스 B는 someMethod ()의 원래 구현보다 높은 “internal”액세스 수준으로 someMethod ()를 재정의합니다.
public class A {
fileprivate func someMethod() {}
}
internal class B: A {
override internal func someMethod() {}
}
수퍼 클래스의 멤버에 대한 호출이 허용 된 액세스 수준 컨텍스트 내에서 발생하는 한 서브 클래스 멤버가 서브 클래스 멤버보다 액세스 권한이 낮은 수퍼 클래스 멤버를 호출하는 것도 유효합니다.(즉, file-private 멤버 호출의 경우 수퍼 클래스와 동일한 소스 파일 내에서 또는 internal 멤버 호출의 경우 수퍼 클래스와 동일한 모듈 내에서) :
public class A {
fileprivate func someMethod() {}
}
internal class B: A {
override internal func someMethod() {
super.someMethod()
}
}
수퍼 클래스 A와 서브 클래스 B는 동일한 소스 파일에 정의되어 있으므로 someMethod ()의 B 구현에서 super.someMethod ()를 호출하는 것이 유효합니다.
Constants, Variables, Properties, and Subscripts
상수, 변수, 속성 및 첨자
상수, 변수 또는 속성은 타입보다 더 많이 공개 될 수 없습니다. 예를 들어 private 타입으로 public 프로퍼티를 작성하는 것은 유효하지 않습니다. 마찬가지로 아래 첨자는 색인 유형이나 반환 유형보다 더 공개 될 수 없습니다.
상수, 변수, 속성 또는 아래 첨자가 전용 유형을 사용하는 경우 상수, 변수, 속성 또는 아래 첨자도 private으로 표시되어야합니다.
private var privateInstance = SomePrivateClass()
Getters and Setters
상수, 변수, 속성 및 첨자에 대한 게터 및 세터는 이들이 속한 상수, 변수, 속성 또는 첨자와 동일한 액세스 수준을 자동으로 받습니다.
setter에 해당 getter보다 낮은 액세스 수준을 제공하여 해당 변수, 속성 또는 아래 첨자의 읽기-쓰기 범위를 제한 할 수 있습니다. var 또는 첨자 소개 자 앞에 fileprivate (set), private (set) 또는 internal (set)을 작성하여 더 낮은 액세스 수준을 할당합니다.
NOTE
이 규칙은 저장된 속성과 계산 된 속성에 적용됩니다. 저장된 속성에 대해 명시적인 getter 및 setter를 작성하지 않더라도 Swift는 저장된 속성의 백업 저장소에 대한 액세스를 제공하기 위해 여전히 암시 적 getter 및 setter를 합성합니다. fileprivate (set), private (set) 및 internal (set)을 사용하여 계산 된 속성의 명시 적 setter와 똑같은 방식으로이 합성 된 setter의 액세스 수준을 변경합니다.
아래 예제는 문자열 속성이 수정 된 횟수를 추적하는 TrackedString이라는 구조를 정의합니다.
struct TrackedString {
private(set) var numberOfEdits = 0
var value: String = "" {
didSet {
numberOfEdits += 1
}
}
}
TrackedString 구조체는 초기 값이 “”(빈 문자열) 인 value라는 저장된 문자열 프로퍼티를 정의합니다. 이 구조체는 값이 수정 된 횟수를 추적하는 데 사용되는 numberOfEdits라는 저장된 정수 프로퍼티도 정의합니다. 이 수정 추적은 value 속성의 didSet 속성 관찰자로 구현되며, value 속성이 새 값으로 설정 될 때마다 numberOfEdits가 증가합니다.
TrackedString 구조체와 value 프로퍼티는 명시적인 액세스 수준 수정자를 제공하지 않으므로 둘 다 기본 액세스 수준 인 internal을 받습니다. 그러나 numberOfEdits 속성에 대한 액세스 수준은 private (set) 한정자로 표시되어 프로퍼티의 getter에 여전히 internal 액세스 수준이 기본적으로 있지만 TrackedString 구조체의 일부인 코드 내에서만 프로퍼티를 설정할 수 있음을 나타냅니다. 이렇게하면 TrackedString이 내부적으로 numberOfEdits 속성을 수정할 수 있지만 구조체의 정의 외부에서 사용될 때 속성을 읽기 전용 속성으로 표시 할 수 있습니다.
TrackedString 인스턴스를 만들고 문자열 값을 몇 번 수정하면 수정 횟수와 일치하도록 numberOfEdits 속성 값 업데이트를 볼 수 있습니다.
var stringToEdit = TrackedString ()
stringToEdit.value = "이 문자열은 추적됩니다."
stringToEdit.value + = "이 편집은 numberOfEdits를 증가시킵니다."
stringToEdit.value + = "이것도 마찬가지입니다."
print ( "편집 횟수는 \ (stringToEdit.numberOfEdits)")
// "편집 횟수는 3입니다."을 인쇄합니다.
다른 소스 파일 내에서 numberOfEdits 프로퍼티의 현재 값을 쿼리 할 수 있지만 다른 소스 파일에서 프로퍼티를 수정 할 수는 없습니다. 이 제한은 TrackedString 편집 추적 기능의 구현 세부 사항을 보호하는 동시에 해당 기능의 측면에 대한 편리한 액세스를 제공합니다.
필요한 경우 getter 및 setter 모두에 대해 명시 적 액세스 수준을 할당 할 수 있습니다. 아래 예제는 구조체가 명시 적 액세스 수준 public으로 정의 된 TrackedString 구조체의 버전을 보여줍니다. 따라서 구조체의 구성원 (numberOfEdits 속성 포함)에는 기본적으로 internal 액세스 수준이 있습니다. public 및 private (set) 액세스 수준 수정자를 결합하여 구조체의 numberOfEdits 속성 getter를 public으로 만들고 속성 setter를 private으로 만들 수 있습니다.
public struct TrackedString {
public private(set) var numberOfEdits = 0
public var value: String = "" {
didSet {
numberOfEdits += 1
}
}
public init() {}
}
Initializers
초기화
사용자 지정 이니셜 라이저에는 초기화하는 타입보다 작거나 같은 액세스 수준을 할당 할 수 있습니다. 유일한 예외는 필수 이니셜 라이저 (필수 이니셜 라이저에 정의 됨)입니다. 필수 이니셜 라이저는 자신이 속한 클래스와 동일한 액세스 수준을 가져야합니다.
함수 및 메서드 매개 변수와 마찬가지로 이니셜 라이저의 매개 변수 타입은 이니셜 라이저의 자체 액세스 수준보다 더 비공개 일 수 없습니다.
Default Initializers
기본 초기화
기본 이니셜 라이저에 설명 된대로 Swift는 모든 프로퍼티에 대한 기본값을 제공하고 하나 이상의 이니셜 라이저 자체를 제공하지 않는 구조체 또는 기본 클래스에 대한 인수 없이 기본 이니셜 라이저를 자동으로 제공합니다.
기본 이니셜 라이저는 해당 유형이 public으로 정의되지 않는 한 초기화하는 유형과 동일한 액세스 수준을 갖습니다. public으로 정의 된 타입의 경우 기본 이니셜 라이저가 internal로 간주됩니다. 다른 모듈에서 사용할 때 인수 없는 이니셜 라이저로 public 형식을 초기화하려면 타입 정의의 일부로 public 형식 없는 이니셜 라이저를 명시 적으로 제공해야합니다.
Default Memberwise Initializers for Structure Types
구조체 유형에 대한 기본 멤버 별 이니셜 라이저
구조체 유형에 대한 기본 멤버 별 이니셜 라이저는 구조체의 저장된 프로퍼티 중 하나라도 private 인 경우 비공개로 간주됩니다. 마찬가지로 구조체의 저장된 속성 중 하나라도 file private 인 경우 이니셜 라이저는 file private입니다. 그렇지 않으면 이니셜 라이저의 액세스 수준은 internal입니다.
위의 기본 이니셜 라이저와 마찬가지로, 다른 모듈에서 사용될 때 멤버 별 이니셜 라이저로 public 구조체 타입을 초기화 할 수 있도록 하려면 타입 정의의 일부로 public 멤버 별 이니셜 라이저를 직접 제공해야합니다.
Protocols
프로토콜
프로토콜 타입에 명시 적 액세스 수준을 할당하려면 프로토콜을 정의하는 지점에서 지정하여야 합니다. 이를 통해 특정 액세스 컨텍스트 내에서만 채택 할 수있는 프로토콜을 만들 수 있습니다.
프로토콜 정의 내 각 요구 사항의 액세스 수준은 프로토콜과 동일한 액세스 수준으로 자동 설정됩니다. 프로토콜 요구 사항을 지원하는 프로토콜과 다른 액세스 수준으로 설정할 수 없습니다. 이렇게하면 프로토콜을 채택하는 모든 유형에서 프로토콜의 모든 요구 사항을 볼 수 있습니다.
NOTE
public 프로토콜을 정의하는 경우 프로토콜의 요구 사항이 구현 될 때 해당 요구 사항에 대한 public 액세스 수준이 필요합니다. 이 동작은 public 타입 정의가 해당 타입의 멤버에 대한 internal 액세스 수준을 의미하는 다른 타입과 다릅니다.
Protocol Inheritance
프로토콜 상속
기존 프로토콜에서 상속하는 새 프로토콜을 정의하는 경우 새 프로토콜은 상속 된 프로토콜과 최대 동일한 액세스 수준을 가질 수 있습니다. 예를 들어 internal 프로토콜에서 상속되는 public 프로토콜을 작성할 수 없습니다.
Protocol Conformance
프로토콜 적합성
타입은 타입 자체보다 액세스 수준이 낮은 프로토콜을 따를 수 있습니다. 예를 들어, 다른 모듈에서 사용할 수 있지만 internal 프로토콜에 대한 적합성은 internal 프로토콜의 정의 모듈 내에서만 사용할 수있는 public 타입을 정의 할 수 있습니다.
타입이 특정 프로토콜을 따르는 컨텍스트는 타입의 액세스 수준과 프로토콜의 액세스 수준의 최소값입니다. 예를 들어,타입이 public이지만 준수하는 프로토콜이 internal 인 경우 해당 프로토콜에 대한 유형의 준수도 internal 입니다.
프로토콜을 준수하기 위해 타입을 작성하거나 확장 할 때 각 프로토콜 요구 사항의 타입 구현이 해당 프로토콜에 대한 타입의 준수와 최소한 동일한 액세스 레벨을 가지고 있는지 확인해야합니다. 예를 들어, public 타입이 internal 프로토콜을 준수하는 경우 각 프로토콜 요구 사항의 유형 구현은 최소한 내부적(internal)이어야합니다.
NOTE
Objective-C 에서처럼 Swift에서 프로토콜 준수는 전역적입니다. 동일한 프로그램 내에서 타입이 두 가지 다른 방식으로 프로토콜을 준수하는 것은 불가능합니다.
Extensions
익스텐션
클래스, 구조체 또는 열거형을 사용할 수 있는 모든 액세스 컨텍스트에서 클래스, 구조체 또는 열거형을 확장 할 수 있습니다. 익스텐션에 추가 된 모든 타입 멤버는 확장중인 원래 타입에서 선언 된 타입 멤버와 동일한 기본 액세스 수준을 갖습니다. public 또는 internal 유형을 확장하는 경우 추가하는 모든 새 유형 멤버는 기본 액세스 수준이 internal입니다. file-private 유형을 확장하는 경우 추가하는 모든 새 유형 멤버는 기본 액세스 수준 인 file-private을 갖습니다. private 유형을 확장하는 경우 추가하는 모든 새 유형 멤버는 기본 액세스 수준이 private 입니다.
또는 명시 적 액세스 수준 수정 자 (예 : private)로 확장을 표시하여 익스텐션 내에 정의 된 모든 구성원에 대한 새 기본 액세스 수준을 설정할 수 있습니다. 이 새로운 기본값은 개별 형식 멤버의 익스텐션 내에서 계속 재정의 할 수 있습니다.
익스텐션을 사용하여 프로토콜 준수를 추가하는 경우 익스텐션에 대한 명시 적 액세스 수준 수정자를 제공 할 수 없습니다. 대신 프로토콜의 자체 액세스 수준을 사용하여 확장 내의 각 프로토콜 요구 사항 구현에 대한 기본 액세스 수준을 제공합니다.
Private Members in Extensions
확장의 private 맴버
익스텐션하는 클래스, 구조체 또는 열거형과 동일한 파일에있는 익스텐션은 익스텐션의 코드가 원래 유형 선언의 일부로 작성된 것처럼 작동합니다. 결과적으로 다음을 수행 할 수 있습니다.
- 원래 선언에서 전용 멤버를 선언하고 동일한 파일의 익스텐션에서 해당 멤버에 액세스할 수 있습니다.
- 한 익스텐션에서 private 멤버를 선언하고 동일한 파일의 다른 익스텐션에서 해당 멤버에 액세스 할 수 있습니다.
- 익스텐션에서 private 멤버를 선언하고 동일한 파일의 원래 선언에서 해당 멤버에 액세스 할 수 있습니다.
이 동작은 유형에 private 항목이 있는지 여부에 관계없이 동일한 방식으로 익스텐션을 사용하여 코드를 구성 할 수 있음을 의미합니다. 예를 들어 다음과 같은 간단한 프로토콜이 있습니다.
protocol SomeProtocol {
func doSomething()
}
익스텐션을 사용하여 다음과 같이 프로토콜 준수를 추가 할 수 있습니다.
struct SomeStruct {
private var privateVariable = 12
}
extension SomeStruct: SomeProtocol {
func doSomething() {
print(privateVariable)
}
}
Generics
제네릭
제네릭 유형 또는 제네릭 함수에 대한 액세스 수준은 제네릭 유형 또는 함수 자체의 액세스 수준과 해당 유형 매개 변수에 대한 모든 유형 제약 조건의 액세스 수준의 최소값입니다.
Type Aliases
유형 별칭
사용자가 정의하는 모든 유형 별명은 액세스 제어를 위해 고유 한 유형으로 처리됩니다. 유형 별칭은 별칭이 지정된 유형의 액세스 수준보다 작거나 같은 액세스 수준을 가질 수 있습니다. 예를 들어 private 타입 별칭은 private, file-private, internal, public 또는 open 타입의 별칭을 지정할 수 있지만 public 유형 별칭은 internal, file-private 또는 private 유형의 별칭을 지정할 수 없습니다.
NOTE
이 규칙은 프로토콜 준수를 충족하는 데 사용되는 관련 유형의 유형 별칭에도 적용됩니다.