Swift) Access Control 1


Access Control 1 - Swift 4.2

Access control은 소스 파일과 모듈의 코드에서 코드 일부의 접근을 제한 합니다. swift의 access control 모델은 모듈과 소스 파일의 개념에 기초합니다. 모듈의 경우 swift 키워드를 사용해서 가져올 수 있는 프레임 워크를 말하며, 소스 파일은 모듈내에 하나의 .swift 소스 파일입니다.

Access Levels

Swift에는 다섯 종류의 aceess level이 있습니다. access level은 entity가 정의된 소스 파일 및 소스 파일이 속한 모듈에 상대적이며, open > public > internal > fileprivate > private 순으로 level이 정해집니다.

1. open, public

  • open과 public access는 import 키워드로 정의된 다른 모듈의 소스파일에도 접근이 가능하고, 모듈 내 어디서든 접근이 가능합니다.
open과 public의 다른점
  • open access는 오직 class와 class의 멤버에만 적용 가능합니다. (struct, enum 불가능)
  • open access는 다른 모듈에서 subclass나 override를 할 수 있지만 public access는 불가능합니다. 
For Example:

xcode에서 2개의 소스파일을 만들고 두 클래스를 상속하게 되면, public class를 상속한 클래스에선 다음과 같은 경고 창이 뜨게 됩니다.


이런 특성은 클래스의 멤버(property, function, ...)도 마찬가지입니다.

OpenClass.swift
open class에 open과 public access의 property를 정의해줍니다.


publicVar property에 error가 생기는 것을 확인 할 수 있습니다.
  • open class는 정의된 모듈이나 import 키워드로 정의된 모듈 내에서 subclass 될 수 있습니다.
  • open mebers는 정의된 모듈이나 import 키워드로 정의된 모듈 내에서 override 될 수 있습니다.

2. inernal

  • internal 접근은 모듈내에 정의된 소스파일 내에서 접근이 가능하며, 모듈 밖에서의 접근은 불가합니다. 특히 internal 접근은 앱 또는 프레임워크 내부 structure를 정의할때 사용 됩니다.

3. fileprivate

  • fileprivate 접근은 entity의 사용을 자체 정의된 소스파일로 제한합니다. 세부 정보가 파일내에서 사용될때 fileprivate를 사용해서 특정 function의 구현 정보를 숨깁니다.

4. private

  • private 접근은 entity의 사용을 동일한 파일 내의 declaration과 extension으로 제한합니다. 세부 사항이 single declaration 내에서 사용될때 function의 특정 부분의 구현 정보를 숨깁니다.

Guiding Principle of Access Levels

swift의 access level의 원칙은 ‘No entity can be defined in terms of another entity that has a lower (more restrictive) access level.’ 입니다. access level이 낮은 entity로 다른 entity를 정의 할 수 없다는 원칙인데 예를 보면서 설명합시다.
  1. public 변수는 internal, fileprivate, private type으로 정의 될 수 없습니다. 해당 타입은 public변수가 사용되는 모든 곳에서 사용 할 수 없기 때문입니다. 
  2. function은 parameter나 return type보다 높은 access level을 가질 수 없습니다. 왜냐하면 해당 타입을 surrounding code에서 사용할 수 없는 상황에서 function을 사용 할 수 있기 때문입니다.
2번은 직관적으로 이해되는 반면에 1번의 원칙은 이해가 되지 않아 검색한 결과 stackoverflow에서 좋은 예를 검색했습니다.

질문자는 다음과 같은 class 2개를 만들었습니다.
1
2
3
4
5
6
7
8
9
10
public class Bucket: CustomStringConvertible {
    public let id: Int
    public let name: String
    public let contents: Array<Contents>
    ...
}
class Contents {
    ...
}
cs

그리고 contents 변수에서 다음과 경고가 떴습니다.
Property cannot be declared public because its type uses an internal type
Contents class의 type이 internal이기 때문입니다.(뒤에서 배우겠지만 swift에서 type을 선언하지 않으면 암시적으로 internal type으로 지정) public 변수가 사용될 수 있는 모든 곳에서 internal type이 사용될 수 없기 때문에 경고가 떴습니다.

Default Access Levels

앞에서 얘기한데로 Swift에서는 Type을 명시하지 않으면 암시적으로 internal type이 적용되며(예외 있음), 대부분 경우에 코드에 명시적으로 access level를 지정할 필요가 없습니다.

Access Levels for Single-Target Apps

Single target app을 만들때 앱의 코드들은 app내부에 포함되어있기 때문에 app 모듈 외부에서 코드를 사용할 필요가 없습니다. internal type은 이런 조건에 일치해서 access level을 지정할 필요가 없습니다. app의 모듈에 포함된 세부 정보를 숨기기 위해서는 fileprivate나 private를 사용 할 수 있습니다.

Access Levels for Frameworks

framework를 개발할 때 framework를 open 또는 public으로 지정해서 app 같은 다른 모듈에서 액세스 할 수 있도록 합니다. 이 공용 인터페이스는 framework의 응용 프로그래밍 인터페이스 (API)입니다.

NOTE
framework의 내부 구현은 internal access level을 사용 할 수 있으며, framework의 내부 코드를 숨기기 위해서 fileprivate 또는 private로 표시 할 수 있습니다.
framework의 api에 포함시키려는 entity의 경우 open 또는 public type으로 설정해야 합니다.

Access Levels for Unit Test Targets

Unit test target이 있는 app을 만들때는 app의 코드를 모듈에서 사용할 수 있도록 해야합니다. 기본적으로 open or public access만 다른 모듈에서 접근 할 수 있었습니다. 그러나 unit test target은 internal entity에도 접근이 가능합니다. @testable 속성을 표시해주면 모듈의 internal 엔티티에 접근 할 수 있습니다.
For Example


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

댓글 없음:

Powered by Blogger.