2014-06-12 27 views
10

Tôi tạo ra một lớp chung trong nhanh chóng và tôi muốn để khởi một adapter với kiểu 'AdaptorType', nhưng tôi nhận được một lỗi biên dịchLàm thế nào để xây dựng một đặc tính theo kiểu generic trong Swift?

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

Tôi cũng đã cố gắng khởi nó trong init(), nhưng cùng vấn đề toke place

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

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

Cách thích hợp để có thuộc tính bộ điều hợp được khởi tạo với kiểu chung AdaptorType là gì? Cảm ơn bạn rất nhiều!

EDIT: mã đầy đủ về câu hỏi này

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

bạn có thể vui lòng đăng lớp AdaptorType của mình không? – Emilie

+0

Trừ khi AdaptorType là một chức năng/đóng cửa, nó không thể xây dựng với '()' ... – Palimondo

+0

Để @Emilie: Các mã được đăng. Cảm ơn bạn –

Trả lời

3

Không phải tất cả đối tượng có thể được khởi tạo không có đối số như bạn đang cố gắng làm. Bạn cần phải lấy một ví dụ khởi tạo initializer của bạn lớp

Bạn cũng có thể xác định giao thức của riêng bạn mà đòi hỏi một initializer trống (bằng cách thêm init với nó) và hạn chế AdapterType phải của giao thức

+0

Thực ra tôi đã làm như vậy. Vui lòng xem mã đầy đủ của tôi. Tôi đang nghĩ về generic có thể không phải là giải pháp tốt nhất. Tôi nên sử dụng subclassing. –

+2

@SenshengXu bạn chưa làm điều này. Giao thức của bạn không xác định phương thức init trống. Bạn nên thêm 'init()' vào giao thức – drewag

0

Vì bạn không biết lớp, bạn không biết cách tạo một thể hiện của lớp. Bạn phải lấy một thể hiện trong constructor của bạn.

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

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

Thực tế thú vị: điều này làm cho tai nạn sân chơi.

1

Bạn có thể làm cho một giao thức tuyên bố khởi tạo

protocol HasEmptyInitializer { 
    init() 
} 

Sau đó, có chung phù hợp với các giao thức

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

Bất cứ điều gì mà có thể được thông qua như AdapterType cũng phải phù hợp với giao thức

extension ProductAdaptor : HasEmptyInitializer {} 
Các vấn đề liên quan