# 39, t 포로토콜 doesn& 자신에게 맞지?

39, t 이 Swift 코드 컴파일하십시오 doesn& 왜?

protocol P { }
struct S: P { }

let arr:[P] = [ S() ]

extension Array where Element : P {
    func test<T>() -> [T] {
        return []
    }
}

let result : [S] = arr.test()

컴파일러는 다음과 같이 말합니다. 유형 'P', 'P' 를 포로토콜 &quot &quot 맞지 않습니다. (또는, 이후 버전의 P& # 39, & # 39 를 사용하여 신속하고, "; p& # 39, & # 39 를 준수하는 등 구체적인 유형을 포로토콜. supported.&quot 아닙니다;).

왜안돼요? 이 feels like a hole in the 언어, 잘은 모르겠지만. 나는 이 문제가 있다는 것이 아니라, '도착' 에서 어레이입니다 표시됨과 어레이입니다 of type 프로토콜을 선언하는 것은 이치에 맞지 않는 일을 하면 되죠? 구조체 공급 유형을 정확히 같은 일이 있었다면 생각해봤죠 프로토콜뿐만 도울 수 있는 계층?

질문에 대한 의견 (8)

왜 don& # 39, t 프로토콜뿐만 따를 수 있습니까?

맞춰야 할 수 있는 일반적인 경우에 스스로를 프로토콜뿐만 부실 있다. 어떤 일이 벌어질까 정적 포로토콜 홍보하십시오. 이러한 다음과 같습니다.

  • '정적' 메서드 및 속성
  • 니시알이어스
  • 관련 유형 (비록 이 프로토콜을 사용하는 것을 표시됨과 현재 실제 유형용) 우리는 이러한 요구 사항을 액세스하려면 일반 자리표시자 'T' 어디서 'T: , P "- 하지만 그 자체가 없습니다 # 39 로 there& 액세스하면 프로토콜에 따라 유형, 구체적인 유형을 따르는 포워드하도록 관용으로충만하신 게 전혀 없다. 따라서 'T' 수 'P' 허용할 수 없다. 다음 예에서는 사용할 수 있다면 어떤 일이 벌어질까 고려해보십시오 확장명은 적용할 수 있는 ' [P]': '어레이입니다'
protocol P {
  init()
}

struct S  : P {}
struct S1 : P {}

extension Array where Element : P {
  mutating func appendNew() {
    // If Element is P, we cannot possibly construct a new instance of it, as you cannot
    // construct an instance of a protocol.
    append(Element())
  }
}

var arr: [P] = [S(), S1()]

// error: Using 'P' as a concrete type conforming to protocol 'P' is not supported
arr.appendNew()

아마도 수 없다 '는', ' ()' 에 호출하십시오 아펜드네프 [P] 때문에 'P' (이하 '요소') 가 아닙니다, 따라서 구체적인 유형을 就不可能拥有 인스턴스화됩니다. It 콘크리트 입력되었는지 요소, 위치를 확인할 수 있는 어레이에서는 합니다 'p' 유형 준수하는 것을 촉구했습니다.

39 의 it& 비슷한 상황을 정적 메서드 및 속성 요구 사항:

protocol P {
  static func foo()
  static var bar: Int { get }
}

struct SomeGeneric {

  func baz() {
    // If T is P, what's the value of bar? There isn't one – because there's no
    // implementation of bar's getter defined on P itself.
    print(T.bar)

    T.foo() // If T is P, what method are we calling here?
  }
}

// error: Using 'P' as a concrete type conforming to protocol 'P' is not supported
SomeGeneric<P>().baz()

말할 수 없다. ',' SomeGeneric&lt 측면에서 P&gt. 우리가 필요한 구체적인 구현을 정적 포로토콜 요구 사항 (표시문 어떻게 있습니다 아니요 구현 '정의' foo () '또는' 표시줄에는 위의 예에서). 우리는 이러한 요구 사항을 구현 'P' 를 정의할 수 있으며, 이러한 구체적인 유형을 따르는 'P' 에 대해서만 정의됩니까 확장명은 - 당신은 여전히 그들을 전화를 할 수 없는 'P' 할 수 있다. 이 때문에 완전히 새로운 유형으로 수 없도록 하고, 그냥 우리 자신을 따르는 충스러웠으니 프로토콜을 사용하여 해당 프로토콜의 정적임 요구 사항, 정보기술 (it), t 는 - 이유는열 doesn& # 39. , T # 39 aren& 인스턴스입니다 프로토콜 요구 사항, 실제 인스턴스입니다 전화를 걸 때 문제가 되는 합니다 협력하였습니다 따르는 프로토콜 (즉, 요구 사항을 구현했습니까 합니다). P ',' 로 입력되었는지 호출하십시오 외면하였나니 요구 사항을 협력하였습니다 인스턴스입니다 앞으로 우리가 할 수 있는 구체적인 type& # 39 의 구현 관용으로충만하신 호출하는 그냥 기본 요건. 그러나 이 경우 어떻게 할 수 있는 특별한 규칙의 예외가 될 수 있는 놀라운 프로토콜뿐만 일반 코드 불일치 취급됩니다. 비록 상황이 너무 수 있다는 것, t '요구' 아소샤테트리프 쁘게 isn& # 39 입니다. (현재) 프로토콜을 사용하여 유형으로 못하도록 합니다. 바꿔야 한다고 할 때 자신을 따르는 프로토콜을 사용하여 너로 유형으로 정적임 요구 사항을 향후 버전의 언어를 할 수 있는 옵션이 있다.

  • Edit:* 아래 개척한 이 시스템은 어떤 조언들이요 포착하십시오 처음에 스위프트 등 팀 목표로 하고 있다.
  • '' 프로토콜뿐만 @objc

    사실, 실제로 that& # 39 의 얼마나 정확히 '언어' 프로토콜뿐만 @objc 처리합니다. # 39, don& 때 별로 없는 정적임 요구 사항, 준수하는 것 "이라고 말했다. 다음 컴파일 그냥 그랬다고.

import Foundation

@objc protocol P {
  func foo()
}

class C : P {
  func foo() {
    print("C's foo called!")
  }
}

func baz(_ t: T) {
  t.foo()
}

let c: P = C()
baz(c)

'P', 'T' 따르도록 하는 '배즈' 'P' 는 'T' 할 수 없다 'P' doesn& # 39 경기에서 때문에, 별로 없는 정적임 홍보하십시오. 만약 우리가 더 이상 추가 요구 사항 'P', 예를 들면 정적 컴파일:

import Foundation

@objc protocol P {
  static func bar()
  func foo()
}

class C : P {

  static func bar() {
    print("C's bar called")
  }

  func foo() {
    print("C's foo called!")
  }
}

func baz(_ t: T) {
  t.foo()
}

let c: P = C()
baz(c) // error: Cannot invoke 'baz' with an argument list of type '(P)'

그래서 한 '이 문제에 대한 해결 방법 - 너회의 포로토콜' @objc 수 있다. # 39, 대부분의 경우, 이 isn& 부여된 대로 따를 수 없는 이상적인 해결하십시오 너회의 docname 추상형데이터타입 뿐만 아니라, 이에 따라 it 의 실용적인 수업을 하는 런타임용으로 개발하십시오 obj c 같은 플랫폼에서 리눅스 않고 있어 비 사과. 하지만 이 제한은 하는 의심이 & # 39 는 언어 (하나는) 이 이미 주요 원인 없이 itself& # 39, 정적 요구사양에 포로토콜 따릅니다. '대한' @objc 프로토콜뿐만. 주변의 일반 작성된 코드를 컴파일러에 의해 상당히 간편화된. 왜? 그 때문에 '그냥' @objc 포로토콜 입력되었는지 값은 효과적으로 사용하여 클래스를 참조입니다 objc_msgsend 파견 요구 사항이 ''. 측면, 비사양 '뒤집기' 에 운반할 때 더욱 복잡해진 @objc 포로토콜 입력되었는지 값은 테이블을 중심으로 메모리 관리를 위해 가치와 가운데있게하여 모두 그들의 가치를 결정하는 데 랩된 (잠재적으로 간접적으로 저장됩니까) 구축 및 다양한 요구 사항을 요청할 것으로 보인다. 이 때문에 단순한 표현 '유형' P ',' @objc 프로토콜뿐만 대한 값이 같은 프로토콜을 동일한 메모리 표현이 a & # 39, 일반 value& # 39 공유할 수 있습니다. 일부 유형의 일반 자리표시자 'T: , P ' (예상) 보다 쉽게 할 수 있도록 처음에 스위프트 고객팀에 자체 승인. # 39 의 경우도 있지만, 동일한 isn& 비사양 't' 등 일반 값을 갖고, 현재 @objc 프로토콜뿐만 don& 값이거나 포로토콜 가운데있게하여 t # 39 표. 그러나 이 기능을 할 수 있기를 바랍니다 은 의도적 / 는 '같이' 팀 구성원하고만 롤아웃할 비사양 @objc 프로토콜뿐만 의해 확인된 만큼 슬라바 페스토프 [있는 설명을 sr (55)] [1] 이에 대한 쿼리하지 데이터베이스에구성원을 it (프롬프트될 에서 이 질문은). &gt. 7일 9월 2017년 오후 1 33 셀명 추가되든지 맷 노이부르크 - &gt. &gt. 컴파일하십시오 않습니다. &gt. &gt. @objc 포로토콜 P {} &gt. c 형: P {} &gt. &gt. func process&lt, T: P&gt, (항목: T) - &gt. T 복귀하십시오 항목설명프로세서} { &gt. func f (image: P) {이제 처리됩니까: P = 프로세스 (항목 이미지)} &gt. &gt. '때문에' @objc 추가 컴파일하십시오. 제거하지 않고 다시 컴파일하십시오 있습니다. &gt. 스택 오버플로 () 에 비해 우리 중 일부는 이 놀라운 찾기 및 싶어요 &gt. # 39 에 의한 것인지 알 수 that& 가장자리의 경우 또는 갈레라 컴퍼니. &gt. &gt. 7일 9월 2017년 오후 1 53 셀명 추가되든지 슬라바 페스토프 - &gt. &gt. # 39 의 it& 의도적인 것은 이 버그는 이 제한 해제 - 관한 것입니다. &gt. 제가 말했듯이요 it& # 39 의 까다로운 우리는 아직 구체적인 계획은 모든 don& # 39, 없다. 그래서 # 39 는 어느 날 '에 대한 지원을 용이하게 할 it& 생각하신거야 :에서 비사양 @objc' 프로토콜뿐만 잘 알려져 있다. 하지만 현재 어떤 솔루션뀉뀉뀉뀉 발생합니까 비사양 @objc '대한' 프로토콜뿐만?

확장명은 프로토콜을 구현하는 함께 구속

3.1 의 스위프트, 스케쳐내 확장명으로 구속조건으로 주어진 특정 프로토콜을 통해 있는 일반 자리표시자 또는 연관된 유형 반드시 유형이거나 (구체적인 유형을 따르는 것이 아니라 protocol) - 정의할 수 있는 '=' 구속 (constraint) 이 됩니다. 예를 들어, 우리가 할 수 있는 어레이입니다 확장명은 만들 수 있다.

extension Array where Element == P {
  func test() -> [T] {
    return []
  }
}

let arr: [P] = [S()]
let result: [S] = arr.test()

물론 이 이제 우리에게 온 것을 방지할 수 있는 구체적인 유형을 따르는 'P' 이 있는 어레이에서는 호출하십시오 요소. 우리는 이 문제를 해결할 수 있을 때 추가로 단 정의점에 확장자임 '요소: 앞으로 '= P' p ', 그리고 그냥 드래그합니다 확장명은:

extension Array where Element : P {
  func test() -> [T] {
    return (self as [P]).test()
  }
}

let arr = [S()]
let result: [S] = arr.test()

그러나 it& # 39 의 가치가 있는 만큼 이를 리셋합니다 O (n) 이 각각의 요소 [P] ',' 변환되게 어레이로의 존재의 컨테이너입니다 작업공간에서 사항박스형 할 것이다. 성능이 중요한 경우 다시 구현 방법을 통해 이 문제를 해결할 수 있는 확장명은 됩니다. , T # 39 이 isn& 완전히 만족할 수 있는 솔루션 - 용이하게 할 수 있는 방법을 익스플레스 a & # 39 는 차기 버전의 언어 포함, 프로토콜 유형 또는 # 39 type& 포로토콜 따릅니다. 구속. 가장 일반적인 방식으로 이를 통해 조속한 이전 3.1 tpc. 롭이에요 fs@snapa 자신의 오토메이티드, [P] ',' 는 단순히 구축하십시오 래퍼 대한 유형을 확장명은 수 있는 방법 (s) 를 정의할 수 있습니다.

반군지역 포로토콜 입력되었는지 인스턴스입니다 제한된 수 있는 일반 자리표시자

다음 고려해보십시오 (아닌 나 '이라는 뜻이다) 상황:

protocol P {
  var bar: Int { get set }
  func foo(str: String)
}

struct S : P {
  var bar: Int
  func foo(str: String) {/* ... */}
}

func takesConcreteP(_ t: T) {/* ... */}

let p: P = S(bar: 5)

// error: Cannot invoke 'takesConcreteP' with an argument list of type '(P)'
takesConcreteP(p)

'P' 를 통과할 수 없다 ',' P '를 다케스콘크레테프 (_:)' 로 현재 일반 자리표시자 대체하십시오 수 없다 "고 말했다. P '. # 39 의 let& 살펴 그 중 몇 가지 방법으로 이 문제를 해결할 수 있습니다.

1. 존재의 열기

'P' 가 아닌 '시도중입니다 대체하십시오 T: P ',' P '입력되었는지 와일드링이 자세히 알고 싶다면 우리가 할 수 있는 기본 콘크리트 유형 및 대체하십시오 랩할 파르타잔 그 대신? 이를 위해서는 죄송합니다. 언어 [열기 존재의] [열기] # 39 라는 기능이 있으며, 현재 isn&, 직접 사용자가 사용할 수 없다. 그러나, Swift 열 명 (포로토콜 입력되었는지 값) 가 암시적으로 존재의 액세스하면 그들 (이리에 it 하숙 아웃해야 런타임용으로 개발하십시오 유형 및 접근할 수 있도록 형태로 일반 자리표시자). 우리는 이 사실을 포로토콜 확장명은) 에 'p' 를 활용할 수 있습니다.

extension P {
  func callTakesConcreteP/**/(/*self: Self*/) {
    takesConcreteP(self)
  }
}

그 자체 '일반' 암시적입니다 기록하십시오 자리표시자 확장명은 메서드에서는 데 사용되는 자체 '-' with all behind the scenes 암시적입니다 입력합니다 매개변수입니다 이런 포로토콜 확장명은 멤버. 'P' 를 호출할 때 메서드입니다 포로토콜 입력되었는지 등 구체적인 값을, Swift 하숙 아웃해야 충족하기 위해 '자가' 는 이 기본 유형이 있으며, 일반 자리표시자. 이 때문에 we& # 39, 수 (_:) '을 (를)' 자가 '-' re 호출하십시오 다케스콘크레테프 we& # 39, re 만족할 만한 'T' 을 (를) '자가'. 즉, 이제 기도하라주여

p.callTakesConcreteP()

'T' 와 '다케스콘크레테프 (:)' 가 일반 자리표시자 색상에는 불렀으매 달성됨 기본 콘크리트 유형 (이 경우 'S') 가 있다. 참고로 이 isn& # 39 를 준수하는 등, t, 프로토콜뿐만 &quot themselves&quot, 구체적인 유형을 'P' - # 39, re 대체 we& 아닌 시도하시겠습니까 정적임 추가에는 프로토콜 내에서 이 때 일어나는 것을 요구 사항을 전화하시기 '다케스콘크레테프 (:)'. 자신을 따르는 것을 허용하지 않을 경우 계속 프로토콜뿐만 에서 오프닝 때, 다음 최고의 얼터너티브 약간만이라도 암시적으로 존재의 전달하십시오 시도중입니다 솔리드로 인수를 일반 유형 - 정확히 어떤 일을 했지만, 트램펄린 lionbridge 포로토콜 확장명은 매개변수입니다 효과적으로 없이 그냥 상용구. 그러나 단, t 의 오프닝 존재의 isn& # 39 를 준수하는 일반 해결책을 프로토콜뿐만 않을 것 "이라고 말했다. # 39, t 계약을 이기종 it doesn& 포로토콜 입력되었는지 값뿐만 기본 모음 수 있는 구체적인 유형을 다 다르다. 예를 들어, 고려해야 합니다.

struct Q : P {
  var bar: Int
  func foo(str: String) {}
}

// The placeholder `T` must be satisfied by a single type
func takesConcreteArrayOfP(_ t: [T]) {}

// ...but an array of `P` could have elements of different underlying concrete types.
let array: [P] = [S(bar: 1), Q(bar: 2)]

// So there's no sensible concrete type we can substitute for `T`.
takesConcreteArrayOfP(array) 

또한 같은 이유로, 여러 'T' 매개변수입니다 일으킬 수 있는 함수를, 매개 변수로 나서야 우리는 같은 유형의 경우 두 개의 'P' 값뿐만 인수만 - 그러나 there& # 39 의 무리라구 컴파일 타임에 보장할 수 있다는 것을 우리는 모두 동일한 기본 콘크리트 유형:. 이 문제를 해결하기 위해 문자 지우개 이용할 수 있다.

2. 지우개 구축하십시오 유형

이를 롭이에요 말한다type 지우개 가 가장 일반적인 해결책은 없는 문제를 프로토콜뿐만 준수하는 것 "이라고 말했다. 그들은 줄 수 있게 한 유형을 구체적으로 포로토콜 입력되었는지 인스턴스입니다 따르는 요구 사항을 전달 인스턴스입니다 의해 해당 프로토콜의 기본 인스턴스입니다. 따라서 let& 전달하는 'P' & # 39 의 구축하십시오 유형: 누진치수의 기입란 # 39 의 임의의 따르는 'P' 는 기본 관용으로충만하신 인스턴스입니다 인스턴스입니다 요구 사항:

struct AnyP : P {

  private var base: P

  init(_ base: P) {
    self.base = base
  }

  var bar: Int {
    get { return base.bar }
    set { base.bar = newValue }
  }

  func foo(str: String) { base.foo(str: str) }
}

이제 그냥 '대신' P '니프 의논하십시오 측면에서':

let p = AnyP(S(bar: 5))
takesConcreteP(p)

// example from #1...
let array = [AnyP(S(bar: 1)), AnyP(Q(bar: 2))]
takesConcreteArrayOfP(array)

이제 잠시 고려해보십시오 그냥 왜 그 상자 구축하십시오 했습니다. 지금까지 살펴본 것처럼, Swift 는 이 프로토콜의 초 구체적인 유형을 요구사항뿐 경우의 정적임 홍보하십시오. 'P' 을 구현하는 데 필요한 경우 고려해보십시오 인도하심이라만일 정적 요구 사항 - '그' 니프 가질 것 "이라고 말했다. 하지만 어떻게 해야 이 구축되어 있다. # 39, 임의의 인스턴스들도 'P' re we& 따르는 우리는 여기서 다룰 수 있을지 알 수 없다 - # 39, 구체적인 방법에 대해 해당 don& 추상형데이터타입 정적 요구 사항, 따라서 '이' 니프 구현하십시오 익스플레스 의미 있게 수 없다. 따라서 이 경우에는 전용 솔루션을 정말 유용한) 의 경우 인스턴스입니다 포로토콜 홍보하십시오. 'P' 를 치료할 수 없는 일반적인 경우에, 아직 구체적인 유형을 따르는 'P'. [1]: # 28441 주석문입니다. 페이지 (https://bugs.swift.org/browse/SR-55) =, = com.atlassian.jira.plugin.system.issuetabpanels% 3acomment-tabpanel 28441&amp 포쿠제드콤멘티드?

[열기]: https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md # 존재의 열기

해설 (14)
해결책

편집: 18 개월 정도 작업할 것을 포함, 다른 메이저 릴리즈로의 (제공하는 새로운 진단), 그리고 의견을 @AyBayBay makes me want to 재작성할 이 대답. 새로운 진단 입니다.

&gt. p& # 39, & # 39 를 사용하여 "; p& # 39, & # 39 를 준수하는 등 구체적인 유형을 포로토콜. supported.&quot 않습니다.

실제로 이 모든게 더 많이 있습니다. 이 확장명은:

extension Array where Element : P {

39 'P', 'P' 요소 = t 적용하십시오 doesn& 때 이후 구체적인 것은 고려하지 않고 있다고 준수를 'P'. (이 경우 it box&quot 동일팔레트에 "; 솔루션이므로 아래는 여전히 가장 일반적인 솔루션을.)

이전 대답:

39 의 경우, It& strike&gt &lt, 또 다른 메타티페스. 정말 하고 싶은 것을 구체적 유형: 대부분의 아닌 사소한 전지전능하심이라 얻을 수 있습니다 [P] ',' isn& # 39 는 콘크리트 유형 (rec.601 can& # 39 는 블록 크기, 메모리 할당 알려진 'P') .&lt /strike>; (난 don& # 39 의 진정한, 실제로 that& # 39 것 같지는 않다. 무언가를 만들어낼 수 있습니다 'P' nnt 크기 때문에 [it& # 39 의 수행되 통해 우회] (https://developer.apple.com/videos/play/wwdc2016/416/).) 내가 don& # 39 의 경우, 이는 어떤 증거도 없는 것 같습니다 there& # 39 &quot shouldn& t&quot # 39;;; 작동합니까. 이 같은 매우 많은 것 같은데, 자신들 중의 한 &quot doesn& yet&quot # 39, 빗나갔다. 건이다. (외람되나 it& # 39 의 차이점은 애플은 이러한 경우 무시하려면 얻을 것은 거의 불가능하다.) 사실은, ',' Array&lt P&gt 가변적입니다 될 수 있음을 they& # 39 번 유형 (여기서 '어레이입니다 수 없는') 이 있지만, 아직 구현되지 않은 것을 많이 예리한 모서리 및 일부 작업하십시오 방향선이 메타티페스 건으로 집계됐다. # 39, re going to get a # 39, 내가 don& you& &quot why&quot, 더 나은 것 같지는 않다. 오토메이티드 이상입니다. # 39, t it.&quot 허용하시겠습니까 때문에 doesn& 컴파일러와의 "; (만족시키지 않는, 나도 알아. 내 모든 것을 생명요.)

이 솔루션은 거의 항상 동일팔레트에 창조하셨노 in a box. 우리는 구축하십시오 유형 지우개.

protocol P { }
struct S: P { }

struct AnyPArray {
    var array: [P]
    init(_ array:[P]) { self.array = array }
}

extension AnyPArray {
    func test() -> [T] {
        return []
    }
}

let arr = AnyPArray([S()])
let result: [S] = arr.test()

이 때 직접 빠르게 수행할 수 있는 나는한다 작성되지는 결국), 다만 이 상자를 만들어 사용하면 자동으로 공산이 크다. 바로 이러한 재귀 이넘 기록 했다. 그들을 매우 귀찮은 및 제한 전송되었기 기입란 했습니다, 마지막으로 '간접' 같은 일을 할 수 있도록 더 많은 컴파일러에서 자동으로 덧붙였다.

해설 (7)

"'콜레스티온티페"' 프로토콜을 확장할 경우 '대신' '어레이입니다 ") 로 구속 및 프로토콜에 의해 구체적인 유형, 이전 코드는 다음과 같이 다시 쓸 수 있습니다.

protocol P { }
struct S: P { }

let arr:[P] = [ S() ]

extension CollectionType where Generator.Element == P {
    func test() -> [T] {
        return []
    }
}

let result : [S] = arr.test()
해설 (0)