프로토콜은 Self 또는 AssociatedType 요구 사항이 있으므로 일반 제약 조건으로 만 사용할 수 있습니다.
프로토콜 RequestType이 있고 아래와 같이 associatedType Model이 있습니다.
public protocol RequestType: class {
associatedtype Model
var path: String { get set }
}
public extension RequestType {
public func executeRequest(completionHandler: Result<Model, NSError> -> Void) {
request.response(rootKeyPath: rootKeyPath) { [weak self] (response: Response<Model, NSError>) -> Void in
completionHandler(response.result)
guard let weakSelf = self else { return }
if weakSelf.logging { debugPrint(response) }
}
}
}
이제 모든 실패한 요청의 대기열을 만들려고합니다.
public class RequestEventuallyQueue {
static let requestEventuallyQueue = RequestEventuallyQueue()
let queue = [RequestType]()
}
그러나 let queue = [RequestType]()
Protocol RequestType은 Self 또는 AssociatedType 요구 사항이 있기 때문에 일반 제약 조건으로 만 사용할 수 있다는 오류가 있습니다.
관련 유형을 사용하는 루틴을 추가하기 위해 프로토콜을 조정하는 순간을 가정 해보십시오.
public protocol RequestType: class {
associatedtype Model
var path: String { get set }
func frobulateModel(aModel: Model)
}
그리고 Swift는 RequestType
여러분이 원하는 방식으로 배열을 만들 수 있도록 했습니다. 이러한 요청 유형의 배열을 함수에 전달할 수 있습니다.
func handleQueueOfRequests(queue: [RequestType]) {
// frobulate All The Things!
for request in queue {
request.frobulateModel(/* What do I put here? */)
}
}
나는 모든 것을 표현하고 싶은 시점에 이르렀지만 어떤 유형의 인수를 호출에 전달할지 알아야합니다. 내 RequestType
엔티티 중 일부 는를 LegoModel
, 일부는를 PlasticModel
, 다른 일부 는 PeanutButterAndPeepsModel
. Swift는 모호함에 만족하지 않으므로 연관된 유형이있는 프로토콜의 변수를 선언 할 수 없습니다.
동시에, 예를 들어 RequestType
우리가 모두 LegoModel
. 이것은 합리적으로 보이지만 사실을 표현할 방법이 필요합니다.
이를 수행하는 한 가지 방법은 실제 유형을 추상 모델 유형 이름과 연결하는 클래스 (또는 구조체 또는 열거 형)를 만드는 것입니다.
class LegoRequestType: RequestType {
typealias Model = LegoModel
// Implement protocol requirements here
}
이제 배열을 선언하는 것이 전적으로 합리적입니다. LegoRequestType
왜냐하면 frobulate
모든 배열을 원한다면 LegoModel
매번 전달해야한다는 것을 알고 있기 때문 입니다.
연관 유형과의 이러한 뉘앙스는이를 사용하는 모든 프로토콜을 특별하게 만듭니다. Swift Standard Library에는 가장 주목할만한 Collection
또는 Sequence
.
Collection
프로토콜 을 구현하는 사물의 배열 또는 시퀀스 프로토콜을 구현하는 사물의 집합 을 만들 수 있도록 표준 라이브러리는 "유형 삭제"라는 기술을 사용하여 구조체 유형 AnyCollection<T>
또는 AnySequence<T>
. 유형 삭제 기술은 Stack Overflow 답변에서 설명하기에는 다소 복잡하지만 웹을 검색하면 관련 기사가 많이 있습니다.
YouTube의 PAT (Protocols With Associated Types) 에 대한 Alex Gallagher 의 비디오를 추천 할 수 있습니다 .
코드 디자인을 조금만 변경하면 가능할 수 있습니다. 프로토콜 계층의 맨 위에 비어있는 연관되지 않은 유형의 프로토콜을 추가하십시오. 이렇게 ...
public protocol RequestTypeBase: class{}
public protocol RequestType: RequestTypeBase {
associatedtype Model
var path: Model? { get set } //Make it type of Model
}
public class RequestEventuallyQueue {
static let requestEventuallyQueue = RequestEventuallyQueue()
var queue = [RequestTypeBase]() //This has to be 'var' not 'let'
}
또 다른 예는 RequestType 프로토콜에서 파생 된 클래스를 사용하여 대기열을 만들고 대기열을 함수에 전달하여 적절한 유형을 인쇄하는 것입니다.
public class RequestA<AType>: RequestType{
public typealias Model = AType
public var path: AType?
}
public class RequestB<BType>: RequestType{
public typealias Model = BType
public var path: BType?
}
var queue = [RequestTypeBase]()
let aRequest: RequestA = RequestA<String>()
aRequest.path = "xyz://pathA"
queue.append(aRequest)
let bRequest: RequestB = RequestB<String>()
bRequest.path = "xyz://pathB"
queue.append(bRequest)
let bURLRequest: RequestB = RequestB<URL>()
bURLRequest.path = URL(string: "xyz://bURLPath")
queue.append(bURLRequest)
func showFailed(requests: [RequestTypeBase]){
for request in requests{
if let request = request as? RequestA<String>{
print(request.path!)
}else if let request = request as? RequestB<String>{
print(request.path!)
}else if let request = request as? RequestB<URL>{
print(request.path!)
}
}
}
showFailed(requests: queue)
'Programing' 카테고리의 다른 글
TypeScript에서 jQuery 플러그인 사용 (0) | 2020.11.05 |
---|---|
Android 명명 규칙 (0) | 2020.11.05 |
Angular2 RC5 : '자식 구성 요소'의 알려진 속성이 아니므로 '속성 X'에 바인딩 할 수 없습니다. (0) | 2020.11.05 |
모듈에서 사용 가능한 클래스 찾기 (0) | 2020.11.05 |
bash에서 n 번째 위치 인수를 얻는 방법은 무엇입니까? (0) | 2020.11.05 |