Swift) Access Control 2

Access Control 2 - Swift 4.2


Access Control Syntax

access control의 syntax는 [access level] [type] [name] 순으로 정의 해주면 됩니다.

For Example:
명시적으로 정해주지 않으면 default로 internal이 정의 됩니다.

Custom Types

custom type에 명시적 access level을 지정하려면 type을 정의하는 시점에 지정해야 합니다.
fileprivate Class를 정의한다면, 이 클래스는 fileprivate 클래스가 정의된 소스 파일에서 property, function parameter, return type에서만 사용가능합니다.

type의 access control level은 default access level에도 영향을 미치는데, private나 fileprivate로 type의 access level을 정의한다면 default access level 또한 private나 fileprivate로 됩니다.
그리고 type의 access level을 public이나 internal로 설정한다면 default access level은 internal이 됩니다.

정리하자면,
private or fileprivate -> default access level: private or fileprivate
open, public, internal -> default access level: internal
로 default access level이 인식됩니다.

For Example:

Tuple Types

Tuple type에 대한 access level은 매우 엄격합니다. Tuple type을 정의할때, 하나는 internal type 또 다른 하나는 private type으로 구성한다면 tuple의 type은 private가 됩니다.

note
Tuple type의 access level은 자동으로 추론되며 명시적으로 정의 할수 없습니다.

Function Types

function type의 access level은 parameter type과 return type의 가장 제한적인 access level로 계산됩니다. fuction의 계산된 access level이 context의 default access level과 매치되지 않는다면 명시적으로 function의 정의에 access level을 정의해야 합니다.

위 예제에서 function의 access level를 추론해봅시다. parameter는 없고 return만 존재하는데 return 역시 tuple type입니다. tuple 타입 역시 두 값중 access level이 더 제한적인 level로 정의 되는데, private가 더 제한적이기 때문에 tuple의 access level은 private이고 function 역시 private 입니다.

하지만 위 예제에서는 function의 access level이 정의되지 않았기 때문에 밑의 예 처럼 private라고 명시적으로 표시해주어야 합니다. (someFuction()이 private class내에서 정의되었다면  private을 선언할 필요가 없겠죠?)

Enumeration Types

enumeration의 각각의 케이스는 enumeration이 가지는 access level과 같기 때문에 case 각각의 access level를 설정할 수 없습니다.

Raw Values and Associated Values

enumeration 내에서 raw values나 associated value에 사용되는 type은 enumeration의 access level보다 높은 access level를 가져야 합니다. 예를 들어 internal access level를 가지는 enumeration은 private type을 가지는 raw value type를 사용할 수 없습니다.

Nested Types

private type 안에 정의된 nested types은 자동으로 private access level이 되고 file private type 안에서 정의된 nested types 역시 자동으로 fileprivate가 됩니다.
internal type이나 public type 안에서 정의된 nested types은 자동으로 internal access level이 됩니다.
만약 public type안에 nested type을 internal이 아닌 public으로 사용하고 싶으면 명시적으로 정의하면 됩니다.

Subclassing

subclass는 super class보다 높은 access level을 가질 수 없습니다. 예를 들어 internal access level를 가지는 super class는 public subclass 정의 할 수 없습니다. override를 사용하면 상속된 subclass가 super class보다 덜 제한적인 access level의 member를 가질 수 있습니다.

예를들어 class A는 public class이고 fileprivate access level의 someMethod() member를 가지고 있습니다. class B는 class A를 상속받는 internal class 입니다. class B가 더 제한적인 access level를 가지는데도, internal access level의 someMethod()를 override하고 있는걸 볼 수 있습니다.

그리고 subclass의 멤버가 더 낮은 access level를 가지는 super class의 멤버를 호출 할 수 있습니다. (file private member를 call 할 때 같은 소스파일이거나 internal member를 call 할 때 같은 모듈일 경우)

Constants, Variables, Properties, and Subscripts

constant, variable, property는 해당 타입이 가지는 access level보다 덜 제한적인 access level로 정의 될 수 없습니다. 비슷하게 subscript도 그것의 index나 return type보다 덜 제한적인 access level로 정의 될 수 없습니다.

예를들어 private type의 constant, variable, property, subscript가 있다면 반드시 private를 표시해주어야 합니다.

 private var privateInstance = SomePrivateClass()

Getters and Setters

constants, variables, properties, subscripts의 getter와 setter는 constants, variables, properties, subscripts가 가지는 access level과 동일합니다.

variable, property, subscript의 read-write scope를 제한하기 위해 getter의 access level보다 더 낮은 access level를 setter에 줄 수 있습니다. var나 subscript introducer 전에 fileprivate(set), private(set), internal(set)을 적음으로써 더 낮은 access level를 assign 할 수 있습니다.

note
이 rule은 stored properties뿐만 아니라 computed properties에도 적용됩니다. stored property의 getter와 setter를 명시적으로 작성하지 않아도 swift는 stored property의 backing storage에 접근할 수 있는 getter와 setter를 암시적으로 만듭니다. 
computed property의 명시적으로 나타낸 setter와 동일한 방법으로 sythesized setter의 access level를 fileprivate(set), private(set), internal(set)을 사용해서 변경할 수 있습니다.

string property의 수정된 횟수를 추적하는 'TrackedString' 구조체를 정의해보겠습니다.

이 구조체에는 empty string으로 초기화된 value 프로퍼티가 있고 value의 수정된 횟수를 추적하는 숫자 0으로 초기화된 numberOfEdits 프로퍼티가 존재합니다. 수정된 횟수를 추적하는 로직은 value 프로퍼티의 didSet property observer로 구현되어 있고 value에 새로운 value가 set 될때마다 numberOfEdits의 횟수를 count 시켜주고 있습니다.

'TrackedString' 구조체와 value 프로퍼티는 명시적인 access level의 modifier를 제공하지 않습니다. (default access level에 따라 internal access level이란걸 알 수 있습니다.) 그러나 numberOfEdits property는 private(set) modifier로 나타내져 있습니다. 이는 프로퍼티의 getter는 여전히 internal access level(default access level)을 가지지만 프로퍼티의 settable은 오직 'TrackedString' 구조체의 코드 내에서만 사용할 수 있습니다. (즉 numberOfEdits은 구조체 외부에서 read가 가능하지만 write는 구조체 내부에서만 가능)

TrackedString 인스턴스를 만들고 string value를 수정하면, numberOfEdits 프로버티의 value가 수정 횟수에 따라 update되는 것을 볼 수 있습니다.
다른 소스 파일에서 numberOfEdits의 값을 get할 수 있지만, set할 수는 없습니다. 이런 제한 사항은 TrackedString의 edit-tracking 기능의 구현 세부사항을 보호하면서 해당 기능 측면에 편리하게 액세스 할 수 있도록 합니다.

필요한 경우 getter 및 setter에 대해 명시적인 액세스 수준을 지정할 수 있습니다. 아래 예제는 명시적 public access level로 정의된 structure의 TrackedString 입니다. numberOfEdits property를 포함한 structure의 멤버는 internal access level를 default value로 가집니다. public과 private(set) access level modifier를 이용해서 numberOfEdits 프로퍼티의 getter를 public으로 설정할 수 있고 setter를 private로 설정할 수 있습니다.

나머지 내용은 3편에서 계속하겠습니다. :)

댓글 없음:

Powered by Blogger.