2014-06-12 22 views
10

Ben hızlı bir jenerik sınıfı yarattı ve ben tip 'AdaptorType' ile bir adaptör başlatmak istiyorum, ama ben de) (init bunu initialize çalıştıSwift'de genel türe göre bir özellik nasıl oluşturulur?

class Sample<ItemType, AdaptorType> { 
    var items = Array<ItemType>() 
    let adaptor = AdaptorType() //Error: 'AdaptorType' is not constructible with '()' 
} 

Bir derleme hata aldım ama aynı sorun toke yer

class SampleGnericClass<ItemType, AdaptorType> { 
    var items = Array<ItemType>() 
    let adaptor : AdaptorType 

    init() { 
     adaptor = AdaptorType()  //It doesn't work, same error occors here 
    } 
} 

genel tür AdaptorType başlangıç ​​durumuna adaptör özelliği alma doğru yolu nedir? Çok teşekkür ederim!

DÜZENLEME: Yapmaya çalıştığınız gibi

import UIKit 

protocol XYManagedObject { 

} 

protocol XYNetworkProtocol { 

    typealias ManagedObjectType : XYManagedObject 

    func object(fromItemDictionary dictionary: NSDictionary?) -> ManagedObjectType? 
    func objects(fromEntryDictionary dictionary: NSDictionary?) -> Array<ManagedObjectType>? 
    func actionParameters(page: UInt?) -> (action: String, parameters: Dictionary<String, String>?) 
    func pageSize() -> UInt? // nil for unlimited 
} 

class ProductAdaptor : XYNetworkProtocol { 

    var filter = Dictionary<String, String>() 

    typealias ManagedObjectType = XYProductObject 

    func object(fromItemDictionary dictionary: NSDictionary?) -> ManagedObjectType? { 
     //... Will return an object here 
     return nil 
    } 

    func objects(fromEntryDictionary dictionary: NSDictionary?) -> Array<ManagedObjectType>? { 
     //... will return an array of objects here 
     return nil 
    } 

    func actionParameters(page: UInt?) -> (action: String, parameters: Dictionary<String, String>?) { 
     var parameters = filter 
     if page { 
      parameters["page"] = "\(page!)" 
     } 

     return ("product_list", parameters) 
    } 

    func pageSize() -> UInt? { 
     return 100 
    } 
} 

class XYDataManager<ItemType: XYManagedObject, AdaptorType: XYNetworkProtocol> { 

    var objects = Array<ItemType>() 
    let adaptor = ProductAdaptor() //work around, adaptor should be any type conform to XYNetworkProtocol 

    func loadPage(page: UInt?) -> (hasNextPage: Bool, items: Array<ItemType>?) { 
     let fetcher = XYFetchController() 

     let ap = adaptor.actionParameters(page) 
     if let fetchedResult = fetcher.JSONObjectForAPI(ap.action, parameters: ap.parameters) { 

      let npage = fetchedResult["npage"].integerValue 
      var hasNextPage = true 
      if !npage || !page { 
       hasNextPage = false 
      } 
      else if npage <= page { 
       hasNextPage = false 
      } 

      let objects = adaptor.objects(fromEntryDictionary: fetchedResult) 
      return (hasNextPage, (objects as Array<ItemType>?)) 
     } 
     else { 
      return (false, nil) 
     } 
    } 
} 
+3

Eğer AdaptorType sınıfını gönderebilir misiniz? – Emilie

+0

AdaptorType bir işlev/kapatma olmadıkça, '()' ile yapılamaz ... – Palimondo

+0

@Emilie: Kodları yayınlandı. Teşekkür ederiz –

cevap

3

tüm nesneler kanıtlar olmaksızın başlatıldı verilebilir bu soru hakkında Tam kodları. O protokolün olmak da (buna init ekleyerek) boş bir başlatıcı gerektirir kendi protokolünü tanımlamak mümkün olabilir

size sınıfının başlatıcısı bir başlatıldı örneği alıp AdapterType kısıtlamak zorunda

+0

Aslında ben zaten bunu yapıyorum. Lütfen tam kodumu görüntüleyin. Jenerik düşünürüm en iyi çözüm olmayabilir. Alt sınıflamayı kullanmalıyım. –

+2

@SenshengXu bunu zaten yapmıyorsunuz. Protokolünüz boş bir init yöntemi tanımlamıyor. Protokol'e 'init()' yi eklemelisiniz. – drewag

0

Sınıfı bilmediğinizden, sınıfın bir örneğini nasıl oluşturacağınızı bilmiyorsunuz. Yapıcınıza bir örnek almalısınız.

class SampleGenericClass<ItemType, AdaptorType> { 
    var items = Array<ItemType>() 
    let adaptor : AdaptorType 

    init(a: AdaptorType) { 
     adaptor = a 
    } 
} 

Eğlence gerçeği: Bu, oyun alanını kilitler.

1

Sen başlatıcı ilan eden bir protokol yapabiliriz

protocol HasEmptyInitializer { 
    init() 
} 

Sonra jenerik da protokole uygun olmalıdır protokole AdapterType olarak geçirilen olabilir

class Sample<ItemType, AdaptorType:HasEmptyInitializer> { 
    var items = Array<ItemType>() 
    let adaptor = AdaptorType() 
} 

şey uygun olması

extension ProductAdaptor : HasEmptyInitializer {} 
İlgili konular