[access-modifiers] Swift에 액세스 수정자가 있습니까?

Objective-C 인스턴스에서 데이터는 또는 public일 수 있습니다 . 예를 들면 다음과 같습니다.protectedprivate

@interface Foo : NSObject
{
  @public
    int x;
  @protected:
    int y;
  @private:
    int z;
  }
-(int) apple;
-(int) pear;
-(int) banana;
@end

Swift 참조에서 액세스 수정 자에 대한 언급을 찾지 못했습니다. Swift에서 데이터의 가시성을 제한 할 수 있습니까?



답변

현재 스위프트 3.0.1 있다 액세스 4 단계 최저 (가장 제한)에 가장 높은 (최소 제한)에서 설명을.


1. open그리고public

정의 모듈 (대상) 외부에서 엔티티를 사용할 수 있도록합니다. 일반적으로 프레임 워크에 공용 인터페이스를 지정할 때 사용 open하거나 public액세스합니다.

그러나 open액세스는 클래스 및 클래스 멤버에만 적용public 되며 다음과 같이 액세스 와 다릅니다 .

  • public 클래스와 클래스 멤버는 정의 모듈 (대상) 내에서만 서브 클래스되고 재정의 될 수 있습니다.
  • open 클래스 및 클래스 멤버는 정의 모듈 (대상) 내외에서 서브 클래스 화 및 재정의 될 수 있습니다.
// First.framework – A.swift

open class A {}

// First.framework – B.swift

public class B: A {} // ok

// Second.framework – C.swift

import First

internal class C: A {} // ok

// Second.framework – D.swift

import First

internal class D: B {} // error: B cannot be subclassed

2. internal

정의 모듈 (대상) 내에서 엔티티를 사용할 수 있도록합니다. 일반적으로 internal앱 또는 프레임 워크의 내부 구조를 정의 할 때 액세스를 사용 합니다.

// First.framework – A.swift

internal struct A {}

// First.framework – B.swift

A() // ok

// Second.framework – C.swift

import First

A() // error: A is unavailable

삼. fileprivate

엔티티 사용을 정의 소스 파일로 제한합니다. 일반적으로 fileprivate액세스를 사용 하여 세부 사항이 전체 파일 내에서 사용될 때 특정 기능의 구현 세부 사항을 숨 깁니다.

// First.framework – A.swift

internal struct A {

    fileprivate static let x: Int

}

A.x // ok

// First.framework – B.swift

A.x // error: x is not available

4. private

엔터티 사용을 엔 클로징 선언으로 제한합니다. 일반적으로 private이러한 세부 사항이 단일 선언 내에서만 사용되는 경우 특정 기능의 구현 세부 사항을 숨기기 위해 액세스를 사용합니다.

// First.framework – A.swift

internal struct A {

    private static let x: Int

    internal static func doSomethingWithX() {
        x // ok
    }

}

A.x // error: x is unavailable


답변

스위프트 4 / 스위프트 5

Swift Documentation-Access Control에 언급 된대로 Swift에는 5 가지 액세스 제어가 있습니다 .

  • open public : 모듈의 엔티티 및 정의 모듈을 가져 오는 모든 모듈의 엔티티에서 액세스 할 수 있습니다.

  • internal : 모듈의 엔티티에서만 액세스 할 수 있습니다. 기본 액세스 수준입니다.

  • fileprivate private : 사용자가 정의한 제한된 범위 내에서만 제한적으로 액세스 할 수 있습니다.


공개공개 의 차이점은 무엇입니까 ?

open 은 이전 버전의 Swift에서 공개 된 것과 동일하며 다른 모듈의 클래스가이를 사용하고 상속 할 수 있습니다. 즉, 다른 모듈에서 서브 클래 싱 될 수 있습니다. 또한 다른 모듈의 구성원이이를 사용하고 대체 할 수 있습니다. 모듈에도 동일한 논리가 적용됩니다.

public 은 다른 모듈의 클래스가 클래스를 사용하도록 허용하지만 상속 하지는 않습니다 . 즉, 다른 모듈에서 서브 클래 싱 할 수 없습니다 . 또한 다른 모듈의 구성원이이를 사용할 수 있지만 대체하지는 않습니다. 모듈의 경우 동일한 개방형 논리를 갖습니다 (클래스가 클래스를 사용하고 상속 할 수 있도록 허용합니다.

fileprivateprivate 의 차이점은 무엇입니까 ?

fileprivate 는 전체 파일에서 액세스 할 수 있습니다.

private 은 단일 선언 및 동일한 파일에있는 해당 선언의 확장 으로 만 액세스 할 수 있습니다 . 예를 들어 :

// Declaring "A" class that has the two types of "private" and "fileprivate":
class A {
    private var aPrivate: String?
    fileprivate var aFileprivate: String?

    func accessMySelf() {
        // this works fine
        self.aPrivate = ""
        self.aFileprivate = ""
    }
}

// Declaring "B" for checking the abiltiy of accessing "A" class:
class B {
    func accessA() {
        // create an instance of "A" class
        let aObject = A()

        // Error! this is NOT accessable...
        aObject.aPrivate = "I CANNOT set a value for it!"

        // this works fine
        aObject.aFileprivate = "I CAN set a value for it!"
    }
}


Swift 3과 Swift 4 액세스 제어의 차이점은 무엇입니까?

SE-0169 제안서에 언급 된 바와 같이 , Swift 4에 추가 된 유일한 개선 사항은 개인 액세스 제어 범위가 동일한 파일에서 해당 선언의 확장 에서 액세스 할 수 있도록 확장 되었다는 것입니다. 예를 들어 :

struct MyStruct {
    private let myMessage = "Hello World"
}

extension MyStruct {
    func printMyMessage() {
        print(myMessage)
        // In Swift 3, you will get a compile time error:
        // error: 'myMessage' is inaccessible due to 'private' protection level

        // In Swift 4 it should works fine!
    }
}

그래서 선언 할 필요가 없습니다 myMessage으로 fileprivate 전체 파일에 액세스 할 수는.


답변

Swift 또는 ObjC (또는 ruby ​​또는 java 또는…)에서 “비공개 메소드”를 작성하는 것에 대해 이야기 할 때, 해당 메소드는 실제로 비공개 가 아닙니다 . 주변에 실제 액세스 제어가 없습니다. 약간의 내성도를 제공하는 모든 언어를 통해 개발자는 원하는 경우 클래스 외부에서 해당 값을 얻을 수 있습니다.

우리가 여기서 실제로 이야기하고있는 것은 단지 우리가 원하는 기능 만 제시 하고 “개인”으로 간주하는 나머지 부분을 “숨기는” 공용 인터페이스를 정의하는 방법 입니다.

인터페이스 선언을위한 Swift 메커니즘은 protocol입니다.이 목적으로 사용할 수 있습니다.

protocol MyClass {
  var publicProperty:Int {get set}
  func publicMethod(foo:String)->String
}

class MyClassImplementation : MyClass {
  var publicProperty:Int = 5
  var privateProperty:Int = 8

  func publicMethod(foo:String)->String{
    return privateMethod(foo)
  }

  func privateMethod(foo:String)->String{
    return "Hello \(foo)"
  }
}

프로토콜은 일류 유형이며 유형이 가능한 모든 곳에서 사용할 수 있습니다. 그리고 이런 방식으로 사용되면 구현 유형의 인터페이스가 아닌 자체 인터페이스 만 노출합니다.

따라서 매개 변수 유형 등 MyClass대신에 사용 하는 한 MyClassImplementation모두 작동해야합니다.

func breakingAndEntering(foo:MyClass)->String{
  return foo.privateMethod()
  //ERROR: 'MyClass' does not have a member named 'privateMethod'
}

직접 할당의 경우 Swift에 의존하는 대신 유형을 명시 적으로 명시 해야하는 경우가 있지만 거래 차단기는 거의 보이지 않습니다.

var myClass:MyClass = MyClassImplementation()

이 방법으로 프로토콜을 사용하는 것은 의미적이고, 간결하며, 내 눈에는 ObjC에서이 목적으로 사용했던 클래스 확장과 매우 ​​비슷합니다.


답변

내가 알 수있는 한 키워드 ‘public’, ‘private’또는 ‘protected’는 없습니다. 이것은 모든 것이 공개되었음을 암시합니다.

그러나 애플은 사람들이 ” 프로토콜 “(세계의 인터페이스라고 함)과 팩토리 디자인 패턴 을 사용하여 구현 유형의 세부 사항을 숨길 것을 기대할 수 있습니다 .

어쨌든 사용하기에 좋은 디자인 패턴입니다. 논리 유형 시스템을 동일 하게 유지하면서 구현 클래스 계층 구조 를 변경할 수 있습니다 .


답변

프로토콜, 클로저 및 중첩 / 내부 클래스의 조합을 사용하면 모듈 패턴의 선을 따라 무언가를 사용하여 Swift에서 정보를 숨길 수 있습니다. 매우 깨끗하거나 읽기 쉽지는 않지만 작동합니다.

예:

protocol HuhThing {
  var huh: Int { get set }
}

func HuhMaker() -> HuhThing {
   class InnerHuh: HuhThing {
    var innerVal: Int = 0
    var huh: Int {
      get {
        return mysteriousMath(innerVal)
      }

      set {
       innerVal = newValue / 2
      }
    }

    func mysteriousMath(number: Int) -> Int {
      return number * 3 + 2
    }
  }

  return InnerHuh()
}

HuhMaker()
var h = HuhMaker()

h.huh      // 2
h.huh = 32
h.huh      // 50
h.huh = 39
h.huh      // 59

innerVal과 mysteriousMath는 외부 사용에서 숨겨져 있으며 객체로 길을 찾으려고 시도하면 오류가 발생합니다.

나는 Swift 문서를 읽음으로써 길의 일부에 불과하므로 여기에 결함이 있으면 지적하고 알고 싶습니다.


답변

Xcode 6 베타 4부터 Swift에는 액세스 수정자가 있습니다. 릴리스 정보에서 :

신속한 액세스 제어에는 세 가지 액세스 레벨이 있습니다.

  • 개인 엔티티는 정의 된 소스 파일 내에서만 액세스 할 수 있습니다.
  • 내부 엔터티는 정의 된 대상 내의 어느 곳에서나 액세스 할 수 있습니다.
  • 공개 엔티티는 대상 내 어디에서나 현재 대상 모듈을 가져 오는 다른 컨텍스트에서 액세스 할 수 있습니다.

암시 적 기본값은 internal이므로 응용 프로그램 대상 내에서보다 제한적인 위치를 제외하고 액세스 수정자를 해제 한 상태로 둘 수 있습니다. 프레임 워크 대상에서 (예 : 앱과 공유 또는 Today 뷰 확장간에 코드를 공유하기 위해 프레임 워크를 임베드하는 경우) public프레임 워크의 클라이언트에 노출하려는 API를 지정 하는 데 사용 하십시오.


답변

Swift 3.0은 다섯 가지 액세스 제어를 제공합니다.

  1. 열다
  2. 공공의
  3. 내부의
  4. 개인 파일
  5. 은밀한

공개 액세스 및 공개 액세스를 통해 엔티티를 정의 모듈의 소스 파일 내에서 정의 모듈을 가져 오는 다른 모듈의 소스 파일에서도 사용할 수 있습니다. 프레임 워크에 공용 인터페이스를 지정할 때 일반적으로 공개 또는 공용 액세스를 사용합니다.

내부의 액세스를 통해 정의 모듈의 소스 파일 내에서 엔티티를 사용할 수 있지만 해당 모듈 외부의 소스 파일에서는 사용할 수 없습니다. 일반적으로 앱 또는 프레임 워크의 내부 구조를 정의 할 때 내부 액세스를 사용합니다.

파일 개인 액세스는 엔티티 사용을 자체 정의 소스 파일로 제한합니다. 파일 개인 액세스를 사용하여 세부 사항이 전체 파일 내에서 사용될 때 특정 기능의 구현 세부 사항을 숨기십시오.

개인 액세스는 엔터티 사용을 엔 클로징 선언으로 제한합니다. 세부 사항이 단일 선언 내에서만 사용되는 경우 개인 액세스를 사용하여 특정 기능의 구현 세부 사항을 숨기십시오.

공개 액세스는 최고 (최소 제한) 액세스 수준이고 개인 액세스는 가장 낮은 (가장 제한적) 액세스 수준입니다.

기본 액세스 수준

명시 적 액세스 수준을 직접 지정하지 않으면 코드의 모든 엔터티 (일부 특정 예외 제외)는 기본 액세스 수준이 internal입니다. 결과적으로 대부분의 경우 코드에서 명시 적 액세스 수준을 지정할 필요가 없습니다.

주제에 대한 릴리스 정보 :

public으로 선언 된 클래스는 더 이상 정의 모듈 외부에서 서브 클래 싱 될 수 없으며, public으로 선언 된 메소드는 더 이상 정의 모듈 외부에서 재정의 될 수 없습니다. 클래스를 외부에서 서브 클래스로 만들거나 메소드를 외부에서 재정의하려면 클래스를 공개로 넘어서는 새로운 액세스 수준 인 공개로 선언하십시오. 가져온 Objective-C 클래스 및 메소드는 모두 공개가 아닌 공개로 가져옵니다. @testable 가져 오기를 사용하여 모듈을 가져 오는 단위 테스트는 여전히 공개 또는 내부 클래스를 서브 클래스하고 공개 또는 내부 메소드를 대체 할 수 있습니다. (SE-0117)

자세한 정보 및 세부 사항 :
Swift Programming Language (Access Control)