[英]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.