Access Control(접근제어)는 다른 소스 파일 및 모듈의 코드에서, 코드의 일부에 대한 접근을 제한합니다.
- 모듈 → 시스템(혹은 프로그램)이나 제품 등에서 개별적인 기능이나 역할을 가진 부품, 요소/ import 시킬 수 있는 요소(Framework라고도 할 수 있다 ex. UIkit)
- 소스 파일 → 모듈 내의 단일 swift 소스 파일(ex. viewcontroller.swift)
Access levels
- 아래로 갈수록 접근하기가 어려워진다!
- open & public
- internal
- file-private
- private
Open VS Public
예를 통해서 한번 Open 과 Public의 차이점을 알아보자.
서브 클래싱 관점.
- 먼저 내가 외부의 framework MiroFramework를 만들어줬다고 하자. 그리고 그 안에 각각의 open class와 Public class를 만들어줬다.
// MiroFramework라면
open class OpenClass {
public init(){}
}
public class PublicClass {
public init(){}
}
- 그리고 위와 같은 외부 framework를 import받아 open class instance와 public class instance를 만들어보자.
import MiroFramework
class ViewController: UIviewcontroller {
override func viewDidLoad() {
super.viewDidLoad()
let openClassInstance = OpenClass()
let publicClassInstance = PublicClass()
}
}
- 그리고 아래와 같이 subclassing을 진행하면 open 제어 레벨의 경우에는 외부 framework에서도 서브 클래싱이 가능하지만, public 제어 레벨의 경우에서는 서브 클래싱이 불가능하다.
class SubClass: OpenClass() // OK!
class SubClass: PublicClass() // Error!
그러면 public 제어 레벨 및 internal, file-private, private 경우에는 싹 다 서브클래싱이 불가능할까?
그건 아니다! 같은 framework안에서는 서브클래싱이 가능하다. 즉, MiroFramework안에서는 서브클래싱이 가능하다.
by. Zeddios
📌 open class : Framework내부, Framework외부 (즉 어디서든) 서브클래싱이 가능
public class와 더 제한적인 접근 수준들(internal, File-private, private class) : Framework내부에서만 서브클래싱이 가능
override 관점.
애초에 public의 경우 subclass로 만들수가 없으므로 open 접근제어만 고려해보자!
- 아래와 같이 open func을 만들어주자
// MiroFramework에서
open class OpenClass {
public init(){}
open func someMethod(){}
}
- 아래와 같이 override를 해도 에러가 나지않는다.
// error
class SubClass: OpenClass{
override func someMethod(){
print("")
}
}
반면에!!
- 아래와 같이 public func으로 설정을 했을 경우
// MiroFramework에서
open class OpenClass {
public init(){}
public func someMethod(){}
}
- override 를 할 경우 에러가 난다!
// OK
class SubClass: OpenClass{
override func someMethod(){
print("")
}
}
그러나, 앞서 서브 클래싱과 같게 같은 framework내에서는 override가 가능하다.
📌 **open : class, class 멤버는 정의된 모듈 내에서나, 그 모듈을 import하는 외부 모듈에서나 서브클래싱이나 override가 잘 된다"**
public, internal, File-private, private : class, class멤버는 정의된 모듈 내에서만 서브클래싱이나 override가 된다"
Internal
⇒ internal 접근은 엔티티가 정의 모듈의 모든 소스 파일 내에서 사용되지만, 해당 모듈 외부의 소스파일에서는 사용되지 않도록 합니다. 일반적으로 App이나 Framework의 내부 구조를 정의할 때 internal 접근을 사용합니다.
즉, 모듈 내에서만 사용이 가능하다!
기본 default가 싹 다 internal이다, 따라서 internal이라는 단어가 없어도 다 internal인 것!
예를 통해서 이해해보자
- 아래의 OpenClass는 Internal class이며, someMethod는 internal method이다.
// MiroFramework에서
class OpenClass {
public init(){}
func someMethod(){}
}
- 따라서 아래와 같이 MiroFramework외부에서 OpenClass를 만드려고하면 error가 나오게 된다!
import MiroFramework
class ViewController: UIviewcontroller {
override func viewDidLoad() {
super.viewDidLoad()
// error
let openClassInstance = OpenClass()
}
}
- 그럼 아래와 같이 OpenClass를 Open 제어 레벨로 설정해보자
// MiroFramework에서
open class OpenClass {
public init(){}
func someMethod(){}
}
- 그러면 internal로 설정된 someMethod에 의해서 에러가 생기게된다!
import MiroFramework
class ViewController: UIviewcontroller {
override func viewDidLoad() {
super.viewDidLoad()
let openClassInstance = OpenClass()
// 에러
openopenClassInstance.someMethod()
}
}
File-private
internal이 모듈 내에서 사용이 가능하다면, file-private의 경우 소스 파일 내에서만 사용이 가능하다.
- 아래와 같이 fileprivate class를 정의해보자
fileprivate class FileprivateClass{
public init() {}
}
- 같은 파일 내에서도 private을 붙혀서 instance를 만들어줘야하고, private을 붙혀줘야지 서브클래싱이 가능하다.
private var fileprivateInstance = FileprivateClass()
private class A : FileprivateClass {} // Private or fileprivate을 붙혀준다.
- 단, override를 할 때에는 아무것도 안 붙혀줘도 된다.
open class OpenClass {
fileprivate func someMethod() {}
}
class A : OpenClass{
override func someMethod() {
print("Hello")
}
}
Private
⇒ private접근을 사용하면 단일 정의 내에서만 사용되는 특정 기능 조각의 구현 상세 내역을 숨길 수 있습니다.
- 아래와 같이 Private class를 설정해주면, private을 통하여 instance를 생성할 수 있다. 이렇게 하지 않으면 instance 생성 불가능!
private class PrivateClass{
public init() {}
}
private let someInstance = PrivateClass() //OK
- 그리고 만약 아래와 같이 property에 접근하려고 하면 error가 나게 된다.
private class PrivateClass{
public init() {}
private var name = "Miro"
}
class Test {
private let someInstance = PrivateClass()
func someMethod(){
print(**someInstance.name**) //Error!
}
}
총정리
- Public/Open -> 모듈 외부에서도 사용가능,
- internal -> 같은 모듈 및 프로젝트에서 사용가능
- fileprivate -> 같은 소스파일(swift)
- private -> 같은 클래스 { }안에 있어야된다.
Public, Open 제어자
- 서로 다른 모듈에 있는 메소드, 프로퍼티에 접근을 할 수 있다.
- 단, import를 해주어야된다.
예)
// module contactManager (target contactManager)
public var name: String = "module A"
var number: Int = 1
// module ContactManagerUI (target ContactManagerUI)
import contactManager
print(name) // OK!
print(number) // error
Target membership의 활용
- import를 해줄 필요가 없이(module을 만들어 줄 필요가 없이), 바로 외부 module(target)에서 해당 target의 파일에 접근이 가능하다.
- internal 수준의 메소드, 프로퍼티도 접근가능하다.
- 아래의 코드의 경우, 해당 swift 파일은 ContactManagerUI에서 접근이 가능하다!(internal 메소드, 프로퍼티도 접근 가능!)
UnitTest에서 @testable
- 원래 import를 하면 public, open 메소드, 프로퍼티만 접근이 가능하지만
- @testable를 추가해주면 internal 메소드, 프로퍼디도 접근이 가능해진다!
'Swift' 카테고리의 다른 글
[Swift] guard VS if (0) | 2023.02.04 |
---|---|
[Swift] , 와 &&의 차이점 (0) | 2023.02.04 |
[Swift] 연산 프로퍼티 (0) | 2023.02.04 |
[Swift] 타입 프로퍼티, 타입 메소드 (0) | 2023.02.04 |
[Swift] first 문 (0) | 2023.02.04 |