2016-04-01 23 views
22

Merhaba Protokolüm RequestType'ım var ve aşağıdaki gibi relatedType Modeli var.Protokol yalnızca Genel bir kısıtlama olarak kullanılabilir, çünkü Kendin veya relatedType gereksinimleri vardır

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) } 
     } 
    } 

} 

Şimdi tüm başarısız isteklerin kuyruğunu yapmaya çalışıyorum.

public class RequestEventuallyQueue { 

    static let requestEventuallyQueue = RequestEventuallyQueue() 
    let queue = [RequestType]() 

} 

Ama Öz veya associatedType şartları olduğundan Protokol RequestType sadece genel kısıtlaması olarak kullanılabilir hat let queue = [RequestType]() üzerinde hata alıyorum.

Herhangi bir Yardım memnuniyetle karşılanacaktır. an için varsayalım

cevap

43

biz ilişkili türünü kullanan bir rutin eklemek için protokol ayarlayın:

public protocol RequestType: class { 
    associatedtype Model 
    var path: String { get set } 

    func frobulateModel(aModel: Model) 
} 

Ve Swift sen RequestType dizisi istediğiniz şekilde yapalım edildi. Ben bir işlevi içine bu istek türleri bir dizi geçebileceği:

func handleQueueOfRequests(queue: [RequestType]) { 
    // frobulate All The Things! 

    for request in queue { 
     request.frobulateModel(/* What do I put here? */) 
    } 
} 

ben her şeyi frobulate istediğiniz noktaya indireceğim ama çağrı geçmesine argüman ne tür bilmemiz gerekir. Benim RequestType varlıklarımdan bazıları LegoModel alabilir, bazıları PlasticModel alabilir ve diğerleri PeanutButterAndPeepsModel alabilir. Swift, belirsizlikten memnun değildir, dolayısıyla ilişkili bir türe sahip olan bir protokol değişkenini bildirmenize izin vermez.

Aynı zamanda, hepsi RequestType bir dizi oluşturmak için mükemmel bir anlam ifade ediyor, biz bunların hepsi LegoModel kullanın. Bu makul görünüyor ve öyle, ama bunu ifade etmenin bir yoluna ihtiyacın var. Bunu yapmanın

bir yolu soyut Model tipi adıyla gerçek bir türü ilişkilendiren bir sınıf (ya da yapı veya enum) oluşturmaktır:

class LegoRequestType: RequestType { 
    typealias Model = LegoModel 

    // Implement protocol requirements here 
} 

Şimdi tamamen makul LegoRequestType bir diziyi bildirmek için çünkü biz frobulate istediğimizde, her seferinde bir LegoModel'u geçmek zorunda olduğumuzu biliyoruz.

İlişkili Türlerle ilgili bu nüans, bunları özel kullanan tüm protokolleri yapar. Swift Standard Library, en çok Collection veya Sequence gibi Protokolleri içerir.

Eğer Collection protokolü veya sekans protokolünü uygulayan şeylerin bir dizi uygulamak şeylerin bir dizi oluşturmak için izin vermek için, Standart Kütüphanesi yapı türlerini AnyCollection<T> veya AnySequence<T> oluşturmak için "tip silme" denilen bir teknik kullanır. Tip silme tekniği, Yığın Taşması yanıtında açıklamak için oldukça karmaşıktır, ancak web'de arama yaparsanız, bu konuda çok sayıda makale vardır.

YouTube'da Alex Gallagher on Protocols With Associated Types (PATs) adlı videodan bir video önerebilirim.

+12

"Çözümünüz çok genel *" – Adolfo

+1

Bu sorun için gördüğüm en iyi açıklamalardan biri budur. – Keab42