[Swift 기초] 접근제어

2022. 4. 13. 17:38Swift 기초 정리

728x90

//공부 기록용 포스팅입니다. 틀린 부분이 있을 경우 댓글로 알려주시면 감사합니다! 😎

 

 

 

스위프트의 접근제어는 모듈과 소스파일을 기반으로 설계되어있다.

1. 모듈

  • 배포할 코드의 묶음 단위
  • 하나의 프레임워크, 라이브러리, 애플리케이션이 모듈 단위가 될 수 있다.
  • 스위프트에서는 import 키워드로 불러온다.

 

2. 소스파일

  • 스위프트 소스 코드 파일
  • 통상 파일 하나에 타입 하나만 정의하지만
  • 소스파일 하나에 여러 타입(여러 개의 클래스, 구조체, 열거형)이나 함수 등 많은 것을 정의하거나 구현

 

3. 접근수준(Access Level)

  • 각 타입(클래스, 구조체, 열거형 등)에 특정 접근수준을 지정할 수 있고, 타입 내부의 프로퍼티, 메서드, 이니셜라이저, 서브스크립트 각각에도 접근수준을 지정할 수 있다.
  • open, public, internal, fileprivate, private
  • 접근수준은 기본적으로 모듈과 소스파일에 따라 구분
접근수준 키워드 범위 비고
개방 접근수준 open 모듈 외부까지 클래스에서만 사용
공개 접근수준 public 모듈 외부까지  
내부 접근수준 internal 모듈 내부  
파일외부비공개 접근수준 fileprivate 파일 내부  
비공개 접근수준 private 기능정의 내부  

3-1. 공개 접근수준 public

  • 자신이 구현된 소스파일은 물론, 그 소스파일이 속해 있는 모듈, 그 모듈을 가져다 쓰는 모듈 등 모든 곳에서 사용할 수 있다.
  • 우리가 사용하는 스위프트의 기본 요소는 모두 공개 접근 수준으로 구현 되어 있다고 생각하면 된다.
//스위프트 표준 라이브러리에 정의되어 있는 Bool 타입
/// A value type whose instances are either 'true' or 'false'.
public struct Bool {
       /// Default-initialize Boolean value to 'false'.
       public init()
}

3-2. 개방 접근수준 open

  • 공개(public) 접근 수준 이상으로 높은 접근 수준
  • 클래스와 클래스의 멤버에서만 사용할 수 있다.
  • 공개 접근수준과 차이점
    • 개방 접근 수준을 제외한 다른 모든 접근수준의 클래스는 그 클래스가 정의된 모듈안에서만 사용할 수 있다. (= 공개 접근수준과 개방 접근 수준은 모듈 외부에서도 사용할 수 있다.)
    • 개방 접근 수준을 제외한 다른 모든 접근수준의 클래스 멤버는 해당 멤버가 정의된 모듈 안에서만 재정의 할 수 있다. (= 공개 접근수준과 개방 접근 수준의 클래스 멤버는 모듈 외부에서도 재정의 할 수 있다.)
    • 개방(open) 접근수준의 클래스는 그 클래스가 정의된 모듈 밖의 다른 모듈에서도 상속할 수 있다.
    • 개방(open) 접근수준의 클래스 멤버는 해당 멤버가 정의된 모듈 밖의 다른 모듈에서도 재정의(override)할 수 있다.
    • 클래스를 개방(open) 접근수준으로 명시하는 것은 그 클래스를 다른 모듈에서도 부모 클래스로 사용하겠다는 목적으로 클래스를 설계하고 코드를 작성했음을 의미
//Foundation 프레임워크에 정의되어 있는 개방접근 수준의 NSString 클래스
open class NSString : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
       open var length: Int { get }
       open func character(at index: Int) -> unichar
       public init()
       public init?(coder aDecoder: NSCoder)
}

3-3. open과 public 접근수준의 선택

  • 라이브러리 혹은 프레임 워크를 설계할 때 해당 모듈을 사용하는 프로그래머가 이 타입을 사용할 수 있도록 하려면 open 혹은 public 공개수준으로 타입을 정의하면 된다.
  • open(개방): 사용자가 상속받아 사용 O or 상속 후 재정의 O
  • public(공개): 상속 X, 재정의 X
  • open 및 public 접근 수준이 아닌 다른 클래스 및 타입은 모듈 외부에서 접근할 수 없다.

3-4. 내부 접근 수준 internal

  • 기본적으로 모든 요소에 암묵적으로 지정하는 기본 접근 수준
  • 소스파일이 속해 있는 모듈 어디서든 사용할 수 있다. 다만 그 모듈을 가져다 쓰는 외부 모듈에서는 접근할 수 없다.
  • 외부에서 사용할 클래스나 구조체가 아니며, 모듈 내부에서 광역적으로 사용할 경우 내부 접근 수준을 지정

3-5. 파일외부비공개 접근수준 fileprivate

  • 요소가 구현된 소스파일 내부에서만 사용할 수 있다.

3-6. 비공개 접근수준 private

  • 가장 한정적인 범위
  • 기능을 정의하고 구현한 범위 내에서만 사용할 수 있다.
  • 같은 소스파일 안에 구현한 다른 타입이나 기능에서도 사용할 수 없다.

3-7. 접근수준

(높은 접근수준) open ←→ public ←→ internal ←→ fileprivate ←→ private (낮은 접근수준)

  • 상위 요소보다 하위 요소가 더 높은 접근수준을 가질 수 없다.
    • 비공개 접근 수준으로 정의한 구조체 내부의 프로퍼티로 내부수준이나 공개수준을 갖는 프로퍼티를 정의할 수 없다.
    • 비공개 접근수준 AClass에서 정의한 someMethod() 메서드도 공개 접근 수준을 부여해도 비공개 접근수준으로 취급
    • 공개 접근 수준의 함수에 비공개 접근수준의 매개변수나 리턴타입으로 사용할 수 없다.
private class AClass {
    // 공개 접근수준을 부여해도 AClass의 접근수준이 비공개 접근수준이므로
    // 이 메서드의 접근수준도 비공개 접근수준으로 취급됩니다.
    public func someMethod() {
        // ...
    }
}

//비공개 접근수준 AClass에서 정의한 someMethod() 메서드도 공개 접근 수준을 부여해도 비공개 접근수준으로 취급
// AClass의 접근수준이 비공개 접근수준이므로
// 공개 접근수준 함수의 매개변수나 반환 값 타입으로 사용할 수 없습니다.
public func someFunction(a: AClass) -> AClass {
    // 오류 발생!
    return a
}

//공개 접근 수준의 함수에 비공개 접근수준의 매개변수나 리턴타입으로 사용할 수 없다.

3-8. private와 fileprivate

  • fileprivate 접근 수준은 같은 파일 어떤 코드에서 접근할 수 있다
  • private 접근 수준은 같은 파일 내부에 다른 타입의 코드가 있더라도 접근할 수 없다.
    • 자신을 확장하는 extension 코드가 같은 파일에 존재하는 경우에는 접근할 수 있다.
public struct SomeType {
       private var privateVariable = 0
       fileprivate var fileprivateVariable = 0
}
// 같은 타입의 익스텐션에서는 private 요소에 접근 가능
extension SomeType {
    public func publicMethod() {
        print("\\(self.privateVariable), \\(self.fileprivateVariable)")
    }
    private func privateMethod() {
        print("\\(self.privateVariable), \\(self.fileprivateVariable)")
    }
    fileprivate func fileprivateMethod() {
        print("\\(self.privateVariable), \\(self.fileprivateVariable)")
    }
}
struct AnotherType {
    var someInstance: SomeType = SomeType()
    mutating func someMethod() {
        // public 접근수준에는 어디서든 접근 가능
        self.someInstance.publicMethod() // 0, 0
        // 같은 파일에 속해 있는 코드이므로 fileprivate 접근수준 요소에 접근 가능
        self.someInstance.fileprivateVariable = 100
        self.someInstance.fileprivateMethod() // 0, 100
        // 다른 타입 내부의 코드이므로 private 요소에 접근 불가! 오류!
        // self.someInstance.privateVariable = 100
        // self.someInstance.privateMethod()
    }
}
var anotherInstance = AnotherType()
anotherInstance.someMethod()

 

4. 읽기 전용 구현

  • 저장 프로퍼티를 구현할 때는 허용된 접근수준에서 프로퍼티 값을 가져갈 수 있다. 이때 값을 변경할 수 없도록 구현하고 싶다면 → 설정자(Setter)만 더 낮은 접근수준을 갖도록 제한
    • 설정자: set
    • 접근자: get
  • 요소의 접근 수준 키워드 뒤에 {접근수준}(set)처럼 표현하면 설정자의 접근수준만 더 낮도록 지정할 수 있다.
public private(set) var publicGetOnlyStoredProeprty: Int = 0
  • 설정자의 접근 수준 제한은 프로퍼티, 서브스크립트, 변수 등에 적용될 수 있다.
  • 해당 요소의 접근수준보다 같거나 낮은 수준으로 제한
public struct SomeType {
    // 비공개 접근수준 저장 프로퍼티 count
    private var count: Int = 0
    // 공개 접근수준 저장 프로퍼티 publicStoredProperty
    public var publicStoredProperty: Int = 0
    // 공개 접근수준 저장 프로퍼티 publicGetOnlyStoredProperty
    // 설정자는 비공개 접근수준
    public private(set) var publicGetOnlyStoredProperty: Int = 0
    // 내부 접근수준 연산 프로퍼티 internalComputedProperty
    internal var internalComputedProperty: Int {
        get {
            return count
        }
        set {
            count += 1
        }
    }
    // 내부 접근수준 연산 프로퍼티 internalGetOnlyComputedProperty
    // 설정자는 비공개 접근수준
    internal private(set) var internalGetOnlyComputedProperty: Int {
        get {
            return count
        }
        set {
            count += 1
        }
    }
}

var someInstance: SomeType = SomeType()
// 외부에서 접근자, 설정자 모두 사용 가능
print(someInstance.publicStoredProperty)    // 0
someInstance.publicStoredProperty = 100
// 외부에서 접근자만 사용 가능: 설정자는 비공개 접근수준(private)
print(someInstance.publicGetOnlyStoredProperty) // 0
//someInstance.publicGetOnlyStoredProperty = 100    // 오류 발생
// 외부에서 접근자, 설정자 모두 사용 가능
print(someInstance.internalComputedProperty)    // 0
someInstance.internalComputedProperty = 100
// 외부에서 접근자만 사용 가능: 설정자는 비공개 접근수준(private)
print(someInstance.internalGetOnlyComputedProperty)     // 1
//someInstance.internalGetOnlyComputedProperty = 100    // 오류 발생

 

 

 

 

참고하였습니다. 감사합니다.

https://yagom.net/courses/swift-basic/lessons/접근제어/

 

728x90

'Swift 기초 정리' 카테고리의 다른 글

[Swift 기초] 연산자 오버로딩  (0) 2023.07.11
[Swift 코테 기초] 고차함수  (0) 2022.04.12
[Swift 기초] 오류처리  (0) 2022.04.11
[Swift 기초] 익스텐션  (0) 2022.04.05
[Swift 기초] 프로토콜  (0) 2022.04.05