카테고리 없음

swift 접근제한자 private 공부해보자

kingarthur 2024. 6. 20. 20:47

사용은 하고 있는데 어디에 사용해야 되는지 적합한지 몰라서...공부해볼려 합네다

접근제어 종류

 

Swift에서는 아래의 5개의 접근레벨을 제공합니다.

Keyword Access Level Range
open 개방 접근 수준 모듈 외부에서도 접근 가능
public 공개 접근 수준 모듈 외부에서도 접근 가능
internal 내부 접근 수준 하나의 모듈 내부에서만 접근 가능
fileprivate 파일 내부 접근 수준 하나의 파일 내에서만 접근 가능
Private 비공개 접근 수준 정의한 블록 내부에서만 접근 가능


open & public :

Open과 Public 접근자 모두 선언한 모듈이 아닌 다른 모듈에서 사용가능합니다. 두 접근자의 차이점은 open은 다른 모듈에서 오버라이드와 서브클래싱이 가능하지만 public 접근자로 선언된 것은 다른 모듈에서는 오버라이드와 서브클래싱이 불가능 합니다.

 

internal :

기본 접근레벨로 아무 접근레벨을 선언하지 않으면 internal로 간주됩니다. internal레벨로 선언되면 해당 모듈 전체에서 사용 가능합니다.

 

fileprivate :

특정 엔티티를 선언한 파일 안에서만 사용 가능합니다.

 

private :

특정 엔티티가 선언된 괄호({}) 안에서만 사용 가능합니다.

 

가이드 원칙

 

Swift에서는 아래와 같은 접근레벨 가이드 원칙 (Guiding Principle of Access Levels)을 제공하고 있습니다.

 

  1. public 변수는 다른 internal, file-private 혹은 private 타입에서 정의될 수 없습니다. 왜냐하면 그 타입은 public 변수가 사용되는 모든 곳에서 사용될 수 없을 것이기 때문입니다.
  2. 함수는 그 함수의 파라미터 타입이나 리턴 값 타입보다 더 높은 접근 레벨을 갖을 수 없습니다. 왜냐하면 함수에는 접근 가능하지만 파라미터에 접근이 불가능 하거나 혹은 반환 값 타입보다 접근 레벨이 낮아 함수를 사용하는 관련 코드에서 이용할 수 없을 수 있기 때문입니다.
  3. 아무런 접근 레벨을 명시하지 않은 경우 internal을 갖게 됩니다.
  4. 단일 타겟 앱에서는 특별히 접근레벨을 명시할 필요가 없지만 필요에 따라 fileprivate, private등을 사용해 앱내에서 구현 세부사항을 숨길 수 있습니다.
  5. 기본적으로 open이나 public으로 지정된 엔티티만 다른 모듈에서 접근 가능합니다. 하지만 유닛테스트를 하는 경우 모듈을 import할때 import앞에 @testable이라는 에트리뷰트를 붙여주면 해달 모듈을 테스트가 가능한 모듈로 컴파일해 사용합니다.

사용예시

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 접근레벨은 생략할 수 있습니다.
class SomeInternalClass {} // implicitly internal

 

 

Private의 예제 입니다.

protocol SomeProtocol {
func doSomething()
}

struct SomeStructA {
    private var privateVariable = 12
}

struct SomeStructB {
    public var publicVariable = 13
}

extension SomeStructA: SomeProtocol {
    func doSomething() {
        print(privateVariable)
    }
}

var a = SomeStructA()
a.doSomething()  // 12 출력
// print(a.privateVariable) 에러남.

var b = SomeStructB()
print(b.publicVariable)  // 13출력

 

publicVariable는 인스턴스 객체 b에서 바로 접근 가능합니다.

 

print(b.publicVarialbe) 하면 13이 출력되는 모습.

 

사실 public 말고 internal, fileprivate도 가능해요. open은 class가 아니니 불가능...

 

 

privateVariable은 SomeStruct 안에서만 접근이 가능합니다.

 

그래서 객체 인스턴스화 된 a.privateVariable 는 접근할 수 없는 모습!!

 

a.doSomething()처럼 privateVariable이 접근 가능한 내부 함수를 통하여 사용해야 합니다.

(접근제어 private의 목적인 거죠. 접근을 제한한다.. 내부 괄호 외에서 접근 금지!)

 

 

추가: 선언된 '괄호'안에서만 접근 가능하다. 라고했는데, 만약 .swift 파일의 최상단 import 부분 밑에 private 변수를 선언할 경우에는 해당 swift파일의 어디에서든 사용 가능하게 됩니다. like fileprivate

 

 

이처럼 접근제어자는 정보 은닉의 효과가 있고,

접근성의 차별화를 두어 좀 더 확실한(안전한?) 프로그래밍을 할 수 있도록 도움을 줄 수 있을 것 같아요.

 

 

 

 

 

public과 private의 차이 아시겠죠?

 

접근제어 알아봤습니다!