Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Xcode
- uitableview
- combine
- 리팩토링
- RxCocoa
- Refactoring
- map
- 리펙토링
- Clean Code
- 애니메이션
- ios
- swiftUI
- rxswift
- UITextView
- UICollectionView
- ribs
- 리펙터링
- collectionview
- swift documentation
- 클린 코드
- HIG
- Protocol
- 스위프트
- Human interface guide
- Observable
- clean architecture
- SWIFT
- MVVM
- tableView
- uiscrollview
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift 공식 문서] 26. Access Control (접근제한) 본문
Access Control
- 다른 소스 파일 또는 모듈의 코드에서 코드 부분에 대한 엑세스를 제한
- 코드의 구현 세부 정보를 숨기고 해당 코드에 엑세스하고 사용할 수 있는 기본 인터페이스를 지정 가능
모듈과 소스파일 구분
- 모듈: 배포 단위
- 프레임워크 또는 응용프래그램을 import로 다른 모듈로 가져올 수 있는 성격
- 소스파일: 단순히 소스코드 파일이므로 소스 파일에서 여러 유형에 대한 access control 정의가 가능
Access level
open | 모든 소스 파일에서 해당 level 접근 가능 + 모든 곳에서 서브클래싱 가능 |
public | 모든 소스 파일에서 해당 level 접근 가능 + 같은 모듈 내에서만 서브클래싱 가능 |
internal (외부 모듈에서 코드 확인 불가) | 같은 모듈 내에서만 접근 가능 |
fileprivate (외부 모듈에서 코드 확인도 불가) | 같은 소스파일 내에서만 접근 가능 |
private (외부 모듈에서 코드 확인도 불가) | 클래스 내부에서만 접근 가능 |
디폴트가 internal인 이유
- 일반적으로 단일 대상으로 특정 앱을 만드는데, 이 앱의 접근은 앱 모듈 외부에서 사용하게 만들 필요가 없기 때문
- 단, 외부에서 해당 모듈의 코드를 비공개하고 싶은 경우 fileprivate, private 둘 중 하나로 설정해야 가능
Unit test 관한 접근제한
- 일반적으로 unit test에서는 다른 코드들을 open과 public만 접근 가능하지만, @testable 속성을 이용하면 테스트가 활성화된 모든 코드 접근 가능
블록 내부에서의 접근제한자
- 바깥 블록에서 선언한 access control의 값보다 블록 안에 있는 access control보다 private쪽에 가깝다면 default는 바깥 블록에서 설정한 값으로 자동 세팅
public class SomePublicClass { // explicitly public class
public var somePublicProperty = 0 // explicitly public class member
var someInternalProperty = 0 // implicitly internal class member
fileprivate func someFilePrivateMethod() {} // explicitly file-private class member
private func somePrivateMethod() {} // explicitly private class member
}
class SomeInternalClass { // implicitly internal class
var someInternalProperty = 0 // implicitly internal class member
fileprivate func someFilePrivateMethod() {} // explicitly file-private class member
private func somePrivateMethod() {} // explicitly private class member
}
fileprivate class SomeFilePrivateClass { // explicitly file-private class
func someFilePrivateMethod() {} // implicitly file-private class member
private func somePrivateMethod() {} // explicitly private class member
}
private class SomePrivateClass { // explicitly private class
func somePrivateMethod() {} // implicitly private class member
}
- 주의사항: 클래스에다 붙이는 접근 제한자의 의미는 조금 다른것을 주의
- open class: 다른 모듈에서 해당 클래스를 상속, override 가능
- public class: 다른 모듈에서 접근만 가능하고 상속, override 불가능
- fileprivate class: 해당 클래스의 프로퍼티, 함수, 반환 타입 모두 fileprivate
- swift4.0부터는 private으로 선언해도 extension에서 접근 가능 (단, 같은 파일에서만 가능하고 다른 파일은 불가)
- private 클래스로 선언해도 같은 파일내에서 해당 클래스 접근 가능
- -> private의 개념은 `블럭 내부`에서 접근 가능하다는 의미는 잘못되었고, `같은 블럭에 위치하는 곳`에서 모두 접근이 가능
- 주의: private class여도 내부에 internal인 인스턴스 메소드가 있으면 접근 가능
// A.swift
private class A {
func abc() {
}
}
class B {
func a() {
let s = A() // private 클래스로 선언해도 같은 파일내에서 해당 클래스 접근 가능
s.abc() // private class로 만든 객체를 통해 내부에 internal인 인스턴스 메소드가 있으면 접근 가능
}
}
- private class vs fileprivate class 차이점?: 최상위 fileprivate class는 private class와 동일
- fileprivate class, private class의 차이는 nested 클래스에서 사용할때 영향력을 발휘
private class A {
fileprivate class C {
}
private class D {
}
func abc() {
}
}
class B {
func a() {
let s = A()
s.abc()
let c = A.C() // 가능
let d = A.D // error
}
}
getter, setter
- setter에 해당 getter보다 낮은 액세스 수준을 부여하여 범위 제한
- set만 따로 괄호쳐진 키워드를 사용
fileprivate(set) var a = 0
private(set) var b = 0
internal(set) var c = 0
- stored property 접근 시 외부에서는 읽기만 되고 쓰기는 해당 property가 아닌 computed-property를 이용하도록 하는 방법
// 외부에서는 읽기 전용(internal) stored property 만드는 예시
struct TrackedString {
/// 읽기는 internal 속성 (생략된 형태)
private(set) var numberOfEdits = 0
var value: String = "" {
didSet {
numberOfEdits += 1
}
}
}
// 읽기는 public으로 설정하는 예시
public struct TrackedString {
public private(set) var numberOfEdits = 0
public var value: String = "" {
didSet {
numberOfEdits += 1
}
}
public init() {}
}
초기화 (Initializer)
- 사용자 지정 init은 초기화하는 유형보다 작거나 같은 액세스 수준을 할당 가능
- 주의: required init은 해당 이니셜라이저에 속한 클래스와 동일한 액세스 수준을 가지지 않으면 컴파일에러 발생
Extension
- class, struct, enum을 사용할 수 있는 모든 액세스 컨텍스트에서 모두 extension 가능
- extension으로 추가된 모든 member는 기존에 있던 default access level을 따름
- fileprivate 유형을 extension > 새 유형 멤버도 모두 fileprivate
- extension으로 private 프로퍼티에 접근할 수 있는 것을 주의
// extension에서 private property 접근이 가능
class Temp {
private var a = 0
}
extension Temp {
func printPrivateProperty() {
print(a)
}
}
Typealias
- typealias는 별칭을 지정하려는 유형의 access level보다 작거나 같도록 설정 가능
* 참고
https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html
'swift 공식 문서' 카테고리의 다른 글
Comments