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

时间:2019-04-16 15:45:42

标签: swift generics

我有一个名为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>'

此外,使用协议/扩展路由可能需要在构建这些对象时遇到的每个类型上的扩展,这似乎很笨重。

我觉得应该有一种方法可以做到这一点。还希望当我将这些项目从数组中拉出时,可以避免很多类型检查。

任何人都可以提供任何建议吗?

2 个答案:

答案 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 {}