xcode 如何在 Swift 中通过泛型类型构造属性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24190837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to construct a property by generic type in Swift?
提问by Sensheng Xu
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() 中初始化它,但同样的问题发生
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? Thank you a lot!
使用泛型类型 AdaptorType 初始化适配器属性的正确方法是什么?非常感谢!
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)
}
}
}
回答by drewag
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 限制为该协议
回答by drawnonward
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 {}
回答by teradyl
You may be able to force cast if you know exactly what type your generic is in the case.
如果您确切地知道您的泛型在这种情况下是什么类型,您也许能够强制转换。
回答by Kevin
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.
有趣的事实:这会使操场崩溃。