代码之家  ›  专栏  ›  技术社区  ›  elight

将泛型值参数指定为对象初始化调用的参数

  •  4
  • elight  · 技术社区  · 6 年前

    我有一个结构 Event 用时间和值初始化。

    这个 value 属性的类型在创建事件时确定。它可以是 Int Double 本原的

    我应该如何在swift中实现这一点?

    我希望能够创建一个新的 事件 像这样的对象:

    let event = Event(time: Date.init(), value: EventValue<Double>(40.3467)) 
    

    我发现 this 但我不明白。

    我已经尝试过很多这样的排列,我能做的最好的就是

    struct Event {
      let time: Date
      var value: EventValue? // This line 'requires arguments in <...>'
    }
    
    struct EventValue <T> {
      let value: T?
    }
    
    4 回复  |  直到 6 年前
        1
  •  2
  •   Martin R    6 年前

    如果目的是要有一个(单一的) Event 带A类型 EventValue 可容纳的财产 任何一个 整数 一个双值,然后一个 enum 与相关的价值观将有助于实现这一目标:

    enum EventValue {
        case ival(Int)
        case dval(Double)
    }
    
    struct Event {
        let time: Date
        let value: EventValue
    }
    
    let event1 = Event(time: Date(), value: .dval(40.3467))
    let event2 = Event(time: Date(), value: .ival(1234))
    
        2
  •  4
  •   jscs    6 年前

    自从 EventValue 是泛型的,它不能直接用作属性的类型。*您必须直接指定类型参数,这将为您提供一个始终具有特定类型的 事件值 :

    struct DoubleEvent {    // Please pick a better name, though
        let time: Date
        var value: EventValue<Double>?
    }
    

    或者使容器成为通用的:

    struct Event<T> {
        let time: Date
        var value: EventValue<T>?
    }
    

    在这两种情况下,在创建 Event : let event = Event(time: Date(), value: EventValue(value: 40.3467)) 类型推断将在 事件 它本身是通用的。

    (旁白:请注意,您对 T 只是 Double Int . 例如, let event = Event(time: Date(), value: EventValue(value: "123abc")) 也是可能的。如果你真的想避免这种情况, Martin R's answer gives one solution )


    *在不太详细的情况下,它更像是“创建类型的东西”,而不是类型本身。

        3
  •  3
  •   Robert Dresler Gustavo Vollbrecht    6 年前

    将泛型参数添加到 Event 结构,然后将此类型用于的参数 EventValue

    struct Event<T> {
        let time: Date
        var value: EventValue<T>?
    }
    

    然后初始化 事件值 不指定类型,因为编译器只允许传递与泛型参数约束对应的值。因为参数没有约束,所以它等于 Any ,这样您就可以通过任何类型

    let event = Event(time: Date.init(), value: EventValue(value: 40.3467))
    
        4
  •  0
  •   Cristik    6 年前

    如果你想支持各种 EventValue 在同样的情况下 Event 类型(即没有 事件 )可以存储 事件值 :

    protocol EventValueProtocol {
        var time: Date { get }
        var value: SomeCommonGroundProtocolOrClass
    }
    
    struct Event {
        let time: Date
    
        // note that the generics information is lost
        // when using the protocol
        var value: EventValueProtocol
    
        init<T>(time: Date, value: EventValue<T>) {
            self.time = time
            self.value = value
        }
    }
    
    struct EventValue <T>: EventValueProtocol {
        let value: T?
    }
    

    “类型擦除器”协议的缺点是,您释放了用于 事件值 但是,您可以通过协议中的一些助手方法来解决这个问题。例如,您可以为所有人使用一个公分母 T 为了访问公共功能而使用的通用参数(除非您想切换所有可能的类型,否则您有必要这样做) T 可以采取)。