2014-06-12 8 views
10

I stworzył ogólną klasę w szybki i chciałbym zainicjować adapter z typu „AdaptorType”, ale otrzymał kompilacji błądJak skonstruować właściwość według typu ogólnego w Swift?

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

Próbowałem też zainicjować go w init(), ale sama problem toke miejsce

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

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

Jaki jest właściwy sposób na uruchomienie właściwości adaptera z typowym typem AdaptorType? Dziękuję bardzo!

EDIT: Pełne kody o to pytanie

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

Czy możesz opublikować swoją klasę AdaptorType? – Emilie

+0

O ile parametr AdaptorType nie jest funkcją/zamknięciem, nie można go skonstruować za pomocą '()' ... – Palimondo

+0

Do @Emilie: Opublikowane kody. Dziękuję –

Odpowiedz

3

Nie wszystkie obiekty mogą być inicjowane bez argumentów na to, że staramy się robić. Trzeba wziąć zainicjowany instancji do inicjatora z was klasie

może również być w stanie określić swój własny protokół, który wymaga pusty inicjator (dodając init do niego) i ograniczyć AdapterType być tego protokołu

+0

Właściwie już to robię. Proszę przejrzeć mój pełny kod. Myślę, że generyczny może nie być najlepszym rozwiązaniem. Powinienem użyć podklasy. –

+2

@SenshengXu już tego nie robisz. Twój protokół nie definiuje pustej metody init. Powinieneś dodać 'init()' do protokołu – drewag

0

Ponieważ nie znasz tej klasy, nie wiesz, jak utworzyć instancję klasy. Musisz wziąć instancję w swoim konstruktorze.

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

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

Ciekawostka: powoduje to awarię placu zabaw.

1

Można zrobić protokół, który deklaruje initializer

protocol HasEmptyInitializer { 
    init() 
} 

Następnie mają ogólny zgodne z protokołem

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

niczego, co mogłoby być przekazywane jako AdapterType muszą być także zgodne z protokołem

extension ProductAdaptor : HasEmptyInitializer {}