简体   繁体   English

如何在Swift中通过泛型类型构造属性?

[英]How to construct a property by generic type in Swift?

I created a generic class in swift and I'd like to initialise an adaptor with the type 'AdaptorType', but I received an compiling error 我在swift中创建了一个泛型类,我想初始化一个类型为'AdaptorType'的适配器,但是我收到了一个编译错误

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

I also tried initialise it in init(), but same problem toke place 我也尝试在init()中初始化它,但同样的问题toke place

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

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

What's the right way to get adaptor property initialised with the generic type AdaptorType? 使用泛型类型AdaptorType初始化适配器属性的正确方法是什么? Thank you a lot! 非常感谢!

EDIT : Full codes about this question 编辑 :关于这个问题的完整代码

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

Not all objects can be initialized without arguments like you are trying to do. 并非所有对象都可以在没有您尝试的参数的情况下进行初始化。 You have to take an initialized instance to the initializer of you class 您必须将初始化的实例带到您的类的初始化器

You may also be able to define your own protocol that requires an empty initializer (by adding init to it) and restrict AdapterType to be of that protocol 您也可以定义自己的协议,该协议需要一个空的初始化程序(通过向其添加init )并将AdapterType限制为该协议

You can make a protocol that declares the initializer 您可以创建一个声明初始化程序的协议

protocol HasEmptyInitializer {
    init()
}

Then have the generic conform to the protocol 然后让通用符合协议

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

Anything that might be passed as AdapterType must also conform to the protocol 任何可能作为AdapterType传递的东西也必须符合协议

extension ProductAdaptor : HasEmptyInitializer {}

Since you don't know the class, you don't know how to create an instance of the class. 由于您不了解该类,因此您不知道如何创建该类的实例。 You have to take an instance in your constructor. 你必须在构造函数中获取一个实例。

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

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

Fun fact: this makes the playground crash. 有趣的事实:这会让游乐场崩溃。

You may be able to force cast if you know exactly what type your generic is in the case. 如果你确切知道你的仿制药在这种情况下的类型,你可以强制施放。

Instantiate an object of a generic type in Swift 在Swift中实例化泛型类型的对象

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM