Swift3 변경 점의 후면(액세스 제어/@escalping)

12716 단어 SwiftiOS
안녕하세요.VAILY의 iOS 엔지니어정성껏입니다.
2015년 12월부터 스위프트는 오픈소스가 됐고Swift Evolution(스위프트 언어에 대한 새로운 접근법이 제시된 곳)에서 많은 개발자의 제안을 채택했다.
Swift3의 액세스 제어 및 @escaping에 대한 변경 사항과 배경에 대해 설명합니다.
모든 Swift 언어의 변경 사항은 Swift Evolution에서 확인할 수 있습니다.
변경점뿐만 아니라 결정에 대한 논의 내용은 Swift Evolution Mailing List의 메일 리스트에서 추적할 수 있다.여기서도 읽을 수 있습니다분류하여 보존하다.

액세스 제어


Swift2의 액세스 제어 개념은 private,internal,public 3개다.
Swift 3은 Swift Evolution의 다음 두 가지 제안을 승인했습니다.
  • Scoped Access Level SE-0025
  • Allow distinguishing between public access and public overridability SE-0117
  • 이 변경 사항은 액세스 제어의 규칙을 바꾸고 새로운 키워드fileprivateopen를 추가했습니다.

    fileprivate SE-0025


    SE-0025가 승인됨에 따라 새 액세스 수정자fileprivate가 추가되었습니다.
    결과적으로 Swift3의 액세스 제어 규칙은 다음과 같습니다.
    액세스 수정자
    의향
    SE-0025에 변경 사항이 있습니까?public모듈 외부에서 접근할 수 있습니다.학급이면 물려받을 수도 있고.
    변경 사항 없음internal같은 모듈에 있으면 접근할 수 있습니다
    변경 사항 없음fileprivate동일한 파일 내에서 액세스 가능
    🆕private동일한 범위 내에서만 액세스 가능
    🆕
    SE-0025public에서internal의 의미는 변하지 않았지만 fileprivate의 수식부호가 새로 추가되었다.fileprivate 정의된 파일은 같은 파일에서 이 구성원에 접근할 수 있습니다.이는 Swift2private의 행동과 같다.
    다른 한편private의 사람들은 같은 파일 안에 있어도 학급과 extension 등 범위를 뛰어넘는 접근을 할 수 없다.

    fileprovate가 필요한 이유


    Swift3private는 파일이 아닌 역할 영역private을 의미합니다.fileprivate는 스위프트2private와 같다.fileprivateprivate를 구분할 수 있다면 extension에서만 사용할 수 있는 방법을 추가할 수 있다.
    예를 들어 유지Stack 데이터의 클래스를 만들 때 단독 extension에push 처리와 pop 처리를 쓰고 싶습니다.
    이때 팝()을 진행할 때만 팝 이전의 데이터print를 하려고 한다.이럴 때는 extension에서 사용할 수 있다private.
    class Stack<T> {
        fileprivate var elements = [T]()
    }
    
    // push extension
    extension Stack {
        func push(_ element: T) {
            printStack()    // 呼び出せない
            elements.append(element)
        }
    }
    
    // pop extension
    extension Stack {
        private func printStack() {
            print("Stack: \(elements)")
        }
    
        func pop() -> T? {
            printStack()
            return elements.removeLast()
        }
    }
    
    printStack() 팝 extension에서만 사용하기 때문에 private 정의된 extension에서 호출할 수 없습니다.printStack() 완전히 숨겨져 있다.

    privte extension 및 fileprive


    스위프트extension를 쓸 때 private extension를 쓰면 그extension 안에 있는 멤버가 아무것도 쓰지 않으면 fileprivate와 같은 방문 등급이 된다.extension는 원래 문서의 최고 단계에 선포한 것이고 private extensionprivate의 유효 범위는 전체 문서이다.
    따라서 모든 속성에는 fileprivate라는 동작이 있다.
    아래의 코드는 같다.fileprivate의 쓰기
    class Hoge { }
    extension Hoge {
        fileprivate func methodA() { ... }
        fileprivate func methodB() { ... }
        fileprivate func methodC() { ... }
    }
    
    은연중
    class Hoge { }
    private extension Hoge {
        func methodA() { ... }
        func methodB() { ... }
        func methodC() { ... }
    }
    

    open SE-0117


    SE-017의 승인을 통해 새로운 접근 수식자open가 추가되었습니다.
    결과적으로 Swift3의 액세스 제어 규칙은 다음과 같습니다.
    액세스 수정자
    의향
    SE-017 변경 사항open모듈 외부에서 접근할 수 있습니다.클래스의 말도 계승할 수 있다(Swift2의public와 같은 행위)
    🆕public모듈 외부에서 접근할 수 있습니다.외부에서 반을 물려받을 수 없다
    🆕internal같은 모듈에 있으면 접근할 수 있습니다
    변경 사항 없음fileprivate동일한 파일 내에서 액세스 가능
    변경 사항 없음private동일한 범위 내에서만 액세스 가능
    변경 사항 없음

    오픈이 왜 필요하냐면요.


    다른 언어에서는 다채로운 접근 제어를 할 수 있지만, Swift2에서는 완전히 개방된 public 만 있다.
    오픈소스 라이브러리 등을 공개할 때 클래스를 공개했더라도 승계하기 싫을 때 이용자에게 의지를 명확히 전달할 수 있다.

    Swift2의 final public과 Swift3의 public.


    스위프트2public final와 스위프트3public의 동작은 비슷하지만 엄밀히 보면 다음과 같은 차이가 있다.
    // Swift 2
    public final class Mammal { }
    public class Dog: Mammal { }    // 同一モジュール内でも継承できない
    
    // Swift 3
    public class Mammal { }
    public class Dog: Mammal { }    // 同一モジュール内では継承可能
    

    @escaping SE-0103


    Swift3@noescape의 언어 키워드가 사라지고 방법의 복제 매개 변수는 기본적으로 분리되지 않음@noescape에서 같은 행동으로 바뀌었습니다.
    다른 한편, 방법의 복제 파라미터가 분리된'가능성'일 경우 @escaping 키워드를 사용해야 한다.UIKit에도 애니메이션 처리 등@escaping을 가진 방법이 많기 때문에 이것은 반드시 이해해야 할 개념이다.@noescape: "이탈 안 함", @escaping: "이탈"

    탈의실


    Swift3 기본 클론 매개 변수는 곧 폐기되기 때문에 쓰지 않아도 [weak hoge] 순환 참조가 되지 않습니다.
    class Hoge {
        func useIt(thisClosure: () -> Void) {
            thisClosure()
        }
    }
    let hoge = Hoge()
    // デフォルトで離脱しないクロージャーなので、[weak hoge] を書かなくても循環参照にならない。
    hoge.useIt() { print(hoge) }
    

    분리된 옷장 인스턴스


    아래 코드처럼 파라미터의 복제자thisClosure를 속성에 복제하면 방법이 실행된 후 파라미터의 복제자도 폐기(이탈)되지 않아 컴파일 오류가 발생합니다.
    // コンパイルエラー
    var myPrettyClosure: (() -> Void)? = nil
    func trapIt(thisClosure: () -> Void) {
        thisClosure()
        myPrettyClosure = thisClosure
    }
    

    복제자의 유형 성명에 앞서 쓰기 @escaping 는 컴파일할 수 있습니다.
    // OK
    var myPrettyClosure: (() -> Void)? = nil
    func trapIt(thisClosure: @escaping () -> Void) {
        thisClosure()
        myPrettyClosure = thisClosure
    }
    

    복제자의 기본 행동이 왜 바뀌었는지


    Swift2 이전의 도마뱀붙이 중 강하게 깨닫지 못하면 순환 참조가 발생하기 쉽다.
    Swift3에서 이 순환 참조가 쉽게 발생하지 않도록 폐쇄물은 기본적으로 분리되지 않는다@noescape.
    Swift의 기어오르기 중에는 map, filter, reduce, @noescape가 대표하는 함수형 프로그래밍@escaping 등 많은 사용 방법이 있다.

    총결산


    이번에는 Swift3의 액세스 제어 및 fileprivate에 대해 설명했습니다.
    하지만 스위프트3는 아직도 파괴적인 변화가 많다.private 덕분에 open 더욱 철저한 모듈 접근 제어가 이루어졌고 public 덕분에 외부 접근 가능한 학급이 계승될 수 있는지 없는지를 구분할 수 있었다.
    다음 블로그에서도 Swift Evolution의 다른 변경 사항을 다시 소개하고 싶습니다.
    심혈을 기울여 설계하다.

    좋은 웹페이지 즐겨찾기