【问题标题】:How to construct a property by generic type in Swift?如何在 Swift 中按泛型类型构造属性?
【发布时间】:2014-06-12 17:51:33
【问题描述】:

我在 swift 中创建了一个泛型类,我想用 'AdaptorType' 类型初始化一个适配器,但是我收到了一个编译错误

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

我也尝试在 init() 中对其进行初始化,但出现了同样的问题

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

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

使用泛型 AdaptorType 初始化适配器属性的正确方法是什么?非常感谢!

编辑:关于这个问题的完整代码

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

【问题讨论】:

  • 你能发布你的 AdaptorType 类吗?
  • 除非 AdaptorType 是一个函数/闭包,否则它不能用 '()' 构造...
  • 致@Emilie:已发布代码。谢谢
  • 致@Palimondo:谢谢!我认为函数/闭包可以为我工作。我正在考虑一个新的解决方案。

标签: ios xcode cocoa-touch generics swift


【解决方案1】:

并非所有对象都可以像您尝试做的那样在没有参数的情况下进行初始化。你必须将一个初始化的实例带到你的类的初始化器中

您也可以定义自己的协议,该协议需要一个空的初始化程序(通过添加 init 到它)并将 AdapterType 限制为该协议

【讨论】:

  • 其实我已经这样做了。请查看我的完整代码。我在考虑通用可能不是最好的解决方案。我应该使用子类化。
  • @SenshengXu 你还没有这样做。您的协议未定义空的 init 方法。您应该将init() 添加到协议中
【解决方案2】:

你可以创建一个声明初始化器的协议

protocol HasEmptyInitializer {
    init()
}

然后让泛型符合协议

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

任何可能作为 AdapterType 传递的东西也必须符合协议

extension ProductAdaptor : HasEmptyInitializer {}

【讨论】:

    【解决方案3】:

    由于您不了解类,因此您不知道如何创建该类的实例。您必须在构造函数中获取一个实例。

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

    有趣的事实:这会使操场崩溃。

    【讨论】:

      【解决方案4】:

      如果您确切知道您的泛型在案例中是什么类型,则可以强制强制转换。

      Instantiate an object of a generic type in Swift

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-18
        • 1970-01-01
        相关资源
        最近更新 更多