简体   繁体   English

Swift:使用通用类型参数创建对象数组

[英]Swift: Creating array of objects with generic type parameter

I have a type called Setting that takes a generic type parameter as such: 我有一个名为Setting的类型,该类型需要一个通用类型参数:

Setting<T>

Every setting contains a value that can be an Int32, String, Bool, or a custom object type, etc. Here is some of the full implementation of Setting: 每个设置都包含一个值,该值可以是Int32,String,Bool或自定义对象类型等。以下是Setting的完整实现:

class Setting<T> {
    var key:String?
    var defaultValue:T?
    //...
}

This all works with various type params as expected, however, now there is a requirement for a collection that contains multiple Setting objects that could have various type parameters. 所有这些都可以按预期与各种类型参数一起使用,但是,现在需要一个包含多个Setting对象的集合,这些对象可能具有各种类型参数。 When I declare an array variable of type [Setting] , obviously the compiler expects a type which is unknown at runtime. 当我声明[Setting]类型的数组变量时,显然编译器期望在运行时未知的类型。

I've tried using a protocol and an extension on the types that could be used for the generic type parameter such as this: 我已经尝试过使用协议和类型的扩展名,这些类型可以用于通用类型参数,例如:

protocol SettingProtocol {
    func getType() -> Self.Type
}

extension Int32:SettingProtocol {
    func getType() -> Int32.Type {
        return Int32.self
    }
}

extension String:SettingProtocol {
    func getType() -> String.Type {
        return String.self
    }
}
//...

and declaring my array as 并声明我的数组为

var settings = [Setting<SettingProtocol>]()

but this does not work when I try to append a Setting instance to the array as follows: 但是当我尝试如下将Setting实例追加到数组时,此方法不起作用:

var newSetting = Setting<String>()
newSetting.setDefaultValue(value: "SomeString")
settings?.append(newSetting) // compile error here

and results in the following compiler error: 并导致以下编译器错误:

Cannot convert value of type 'Setting<String>' to expected argument type 'Setting<SettingProtocol>'

Also, using the protocol/extension route might require an extension on every type that might be encountered when building these objects which seems really clunky. 同样,使用协议/扩展路由可能需要在构建这些对象时可能遇到的每种类型上的扩展,这看起来确实很笨重。

I feel like there should be a way to accomplish this. 我觉得应该有一种方法可以做到这一点。 Also hoping that when I pull these items out of the array that I can avoid a lot of type checking. 还希望当我将这些项目从数组中拉出时,可以避免很多类型检查。

Can anyone offer any advice? 谁能提供任何建议?

Change 更改

class Setting<T> 

to

class Setting<T:SettingProtocol>

and try compiling. 并尝试编译。

Actually, you can't define: 实际上,您无法定义:

var settings = [Setting<SettingProtocol>]()

because the generic type of Setting must be one of the concrete types but not the protocol itself. 因为Setting的通用类型必须是具体类型之一,而不是协议本身。 For example, you could declare it as: 例如,您可以将其声明为:

var settings = [Setting<String>]() // since you already implemented extension String:SettingProtocol { ...

Therefore you could append objects of type Setting<String> , however that's not what are you looking for, you need settings to be a heterogeneous container. 因此,您可以追加类型为Setting<String>对象,但这不是您想要的,您需要将settings设为异构容器。

So what you could do is: 因此,您可以做的是:

class Setting {
    var key:String?
    var defaultValue:SettingProtocol?
}

protocol SettingProtocol { }
extension Int32:SettingProtocol {}
extension String: SettingProtocol {}

At this point, you declared defaultValue to be of type SettingProtocol , without the need of dealing with a generic. 在这一点上,你宣布defaultValue是类型SettingProtocol ,而不需要处理一个通用的。

Therefore: 因此:

var newStringSetting = Setting()
newStringSetting.defaultValue = "My String"
settings.append(newStringSetting)

var newInt32Setting = Setting()
newInt32Setting.defaultValue = Int32(100)
settings.append(newInt32Setting)

for setting in settings {
    print(setting.defaultValue)
    // Optional("My String")
    // Optional(100)
}

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

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