我有一个结构Event
,该结构用时间和值初始化。
value
属性的类型是在创建事件时确定的。它可以是Int
或Double
原语之一。
我应该如何在Swift中实现呢?
我希望能够像这样创建一个新的Event
对象:
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?
}
答案 0 :(得分:4)
由于EventValue
是通用属性,因此不能直接用作属性的类型。*您必须直接指定type参数,这将为您提供一个容器,该容器始终具有特定的{ {1}}:
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))
本身是泛型的情况下将使用类型推断进行填充。
(此外:请注意,您没有正式限制Event
只能是T
或Double
。例如,Int
也可以。如果您这样做,希望严格避免这种情况,Martin R's answer gives one solution。)
*无需过多讨论,它更像是“创建类型的事物”,而不是类型本身。
答案 1 :(得分:3)
也将通用参数添加到您的Event
结构中,然后将此类型用于EventValue
的参数
struct Event<T> {
let time: Date
var value: EventValue<T>?
}
然后只初始化EventValue
而不指定类型,因为编译器允许您只传递与通用参数约束相对应的值。而且由于您的参数没有约束,所以它等于Any
,因此您可以传递任何类型
let event = Event(time: Date.init(), value: EventValue(value: 40.3467))
答案 2 :(得分:2)
如果要使用Event
属性的(单个)EventValue
类型,该属性可以容纳 一个整数或一个double值,那么具有关联值的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))
答案 3 :(得分:0)
如果要在相同的EventValue
类型下支持各种Event
(即Event
没有通用名称),则可以存储EventValue
的协议参考:
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?
}
“类型擦除器”协议的缺点是,您松散了用于EventValue
通用参数的类型信息,但是,也许可以通过一些辅助方法来解决此问题。协议。例如,您可以为所有T
泛型参数使用一个公共分母,以访问该公共功能(除非您想切换T
可以接受的所有可能类型,否则您确实需要这样做)。