我有一个名为Setting
的类型,它带有一个通用类型参数,例如:
Setting<T>
每个设置都包含一个可以是Int32,String,Bool或自定义对象类型等的值。这是Setting的一些完整实现:
class Setting<T> {
var key:String?
var defaultValue:T?
//...
}
所有这些都可以按预期与各种类型参数一起使用,但是,现在需要一个包含多个Setting
对象的集合,这些对象可能具有各种类型参数。当我声明类型为[Setting]
的数组变量时,显然编译器期望的类型在运行时是未知的。
我已经尝试过使用协议和类型扩展名,这些类型可以用于通用类型参数,例如:
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
}
}
//...
并将我的数组声明为
var settings = [Setting<SettingProtocol>]()
,但是当我尝试将Setting
实例附加到数组中时,此方法不起作用:
var newSetting = Setting<String>()
newSetting.setDefaultValue(value: "SomeString")
settings?.append(newSetting) // compile error here
并导致以下编译器错误:
Cannot convert value of type 'Setting<String>' to expected argument type 'Setting<SettingProtocol>'
此外,使用协议/扩展路由可能需要在构建这些对象时遇到的每个类型上的扩展,这似乎很笨重。
我觉得应该有一种方法可以做到这一点。还希望当我将这些项目从数组中拉出时,可以避免很多类型检查。
任何人都可以提供任何建议吗?
答案 0 :(得分:1)
更改
class Setting<T>
到
class Setting<T:SettingProtocol>
并尝试编译。
答案 1 :(得分:1)
实际上,您不能定义:
melt
因为通用类型library(reshape2)
melt(mtx)
# Var1 Var2 value
#1 1 1 -1.2070657
#2 2 1 0.2774292
#3 3 1 1.0844412
#4 4 1 -2.3456977
#5 1 2 0.4291247
#6 2 2 0.5060559
#7 3 2 -0.5747400
#8 4 2 -0.5466319
#9 1 3 -0.5644520
#10 2 3 -0.8900378
#11 3 3 -0.4771927
#12 4 3 -0.9983864
必须是具体类型之一,但不是协议本身。例如,您可以将其声明为:
set.seed(1234)
mtx <- array(rep(rnorm(12)), dim = c(4,3))
因此,您可以追加var settings = [Setting<SettingProtocol>]()
类型的对象,但这并不是您想要的,您需要Setting
成为异构容器。
所以您可以做的是:
var settings = [Setting<String>]() // since you already implemented extension String:SettingProtocol { ...
这时,您声明Setting<String>
的类型为settings
,而无需处理泛型。
因此:
class Setting {
var key:String?
var defaultValue:SettingProtocol?
}
protocol SettingProtocol { }
extension Int32:SettingProtocol {}
extension String: SettingProtocol {}