【问题标题】:Swift: Creating array of objects with generic type parameterSwift:使用泛型类型参数创建对象数组
【发布时间】:2019-04-16 15:45:41
【问题描述】:

我有一个名为 Setting 的类型,它采用这样的泛型类型参数:

Setting<T>

每个设置都包含一个值,可以是 Int32、String、Bool 或自定义对象类型等。以下是设置的一些完整实现:​​

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>'

此外,使用协议/扩展路由可能需要对在构建这些看起来非常笨重的对象时可能遇到的每种类型进行扩展。

我觉得应该有办法做到这一点。也希望当我将这些项目从数组中拉出时,我可以避免大量的类型检查。

谁能给点建议?

【问题讨论】:

    标签: swift generics


    【解决方案1】:

    改变

    class Setting<T> 
    

    到

    class Setting<T:SettingProtocol>
    

    并尝试编译。

    【讨论】:

    • 无法解决。 “不支持将 'SettingProtocol' 用作符合协议 'SettingProtocol' 的具体类型”。
    • @AhmadF 你是对的。我必须让我的 Setting 类符合协议,现在它可以工作了
    • @Pheepster 什么?!一个有效的答案如何?你能提到你做了什么让它发挥作用吗?!
    【解决方案2】:

    其实你无法定义:

    var settings = [Setting<SettingProtocol>]()
    

    因为Setting 的泛型类型必须是具体类型之一,但不是协议本身。例如,您可以将其声明为:

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

    因此,您可以附加 Setting&lt;String&gt; 类型的对象,但这不是您要寻找的,您需要 settings 是一个异构容器。

    所以你可以做的是:

    class Setting {
        var key:String?
        var defaultValue:SettingProtocol?
    }
    
    protocol SettingProtocol { }
    extension Int32:SettingProtocol {}
    extension String: SettingProtocol {}
    

    此时,您将defaultValue 声明为SettingProtocol 类型,无需处理泛型。

    因此:

    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)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-27
      • 1970-01-01
      相关资源
      最近更新 更多