2016-06-24 5 views
2

내가스위프트 프로토콜

그러나 인한의 복잡성에 ("데이터 소스"특정 프로토콜을 구현) 속성의 몇 드 정의를 필요로하는 프로토콜 "저장소"를 정의하려고 내 실제 시나리오 중 하나는이 속성 중 하나가 "DataSource"의 서브 프로토콜 일 필요가 있습니다.

나는이 간단한 코드로 문제를 감소 : 컴파일시 오류를 반환

protocol DataSource { } 

protocol ExtraDataSouce: DataSource { 
    func method1() -> String 
} 

struct MyDataSource: ExtraDataSouce { 
    func method1() -> String { 
     return "whatever" 
    } 
} 


protocol Repository { 
    var firstDataSource: DataSource { get } 
    var secondDataSource: DataSource { get } 
} 

struct MyRepository: Repository { 
    var firstDataSource: DataSource 
    var secondDataSource: MyDataSource 
} 

는 "MyRepository"가 "저장소"을 준수하지 않기 때문에. 하지만 실제로 그렇게 생각합니다 ... "MyDataSource"로 정의 된 "MyRepository"에서 "secondDataSource"를 허용하지 않는 이유에 대한 아이디어는 무엇입니까?

답변

1

리포지토리 프로토콜은 DataSource 유형의 2 변수를 구현합니다. 리포지토리 프로토콜을 준수하는 구조체의 변수 유형을 수정하려고 할 때 필수 유형으로 인해이 작업을 수행 할 수 없습니다. 당신은 내가 당신의 질문에 대한 정보 (내가 잘못 어딘가에 경우, 또는 내가 뭔가를 놓칠 경우, 저를 수정하시기 바랍니다) 발견 검색 한 후이 변경에게

protocol Repository { 
    associatedtype type = DataSource 
    var firstDataSource: DataSource { get } 
    var secondDataSource: type { get } 
} 
+2

제발, 왜 이것이 작동하는지 설명해 주시겠습니까? –

+0

DataSource 유형의 secondDataSource var은이 유형 만 강하게 구현해야하기 때문에 associatedtype을 사용하면 Datasource 유형의 객체를 구현할 수 있습니다. –

+0

해답에 설명을 포함하십시오. 우편 번호뿐만 아니라 답변에 항상 설명을 포함시켜야합니다. – luk2302

2

를 만들기 위해 associatedtype를 사용한다 :

에도 논리적 동안 당신의 코드가 작동해야합니다. 신속한 컴파일러는 MyRepository 클래스에서 해당 유형을 선언 할 때 일반 또는 읽기 전용 프로토콜 변수를 사용할 때 대소 문자 구분을하지 않습니다. 이 케이스를 분리하지 않는 Repository

var secondDataSource: DataSource { get set } 

및 컴파일러에 기록 할 경우 다른 단어에서 코드에서 오류가 분명해진다. 나는 네가 원하는 것을 제대로 할 수있는 방법을 찾지 못했다. 원하는 경우 변경 MyRepository에서 secondDataSource 유형 및 추가 변수를 사용 - 명백한

1) 아마도 가장 올바른 방법 : 프로토콜 방식으로

var _secondDataSource: MyDataSource 
var secondDataSource: DataSource { 
     get {return _secondDataSource} 
     set { 
      guard let newValue = newValue as? MyDataSource else { 
       fatalError("MyRepository: attempt to set DataSource type, MyDataSource type expected") 
      } 
      _secondDataSource = newValue 
     } 
    } 

2) 관련 유형은 그러나이 가까이 가지 방법이있다. 여기에 자신의 코드에서 associatedtype type = DataSource 라인은 자리 효과가 있기 때문에 내가 @RaduNunu 응답을 향상하고, 그의 해결책은 당신이 입양에 예를 들어 지금까지 secondDataSource, String의 모든 유형을 선택할 수 있습니다 :

protocol Repository { 
    associatedtype Type = DataSource 
    var firstDataSource: DataSource { get } 
    var secondDataSource: Type { get } 
} 

struct MyRepository: Repository { 
    var firstDataSource: DataSource 
    var secondDataSource: String // - this is ok! 
} 

이 코드는 컴파일을하고 작동하지만 꽤 나빠 보인다. 대신 자리 표시자를 입력하십시오. 프로토콜 적합성을 더 잘 사용하십시오.

protocol Repository { 
    associatedtype Type: DataSource 
    var firstDataSource: DataSource { get } 
    var secondDataSource: Type { get } 
} 

struct MyRepository: Repository { 
    var firstDataSource: DataSource 
    //var secondDataSource: String - this line not allowed now 
    var secondDataSource: MyDataSource 
} 

이 코드는 이미 목표에 매우 가깝습니다. 그러나, 지금부터 당신은 작동하지 않습니다 MyRepository에 관련된 유형으로 프로토콜, 이렇게 선언

var secondDataSource: DataSource 

을 사용할 수 없습니다. 이것은 연관된 유형을 사용하는 데 드는 비용입니다. DataSource 준수 클래스/열거 형/구조체 유형 만 사용할 수 있습니다.

관련 문제