Ich habe eine Struktur Event, die mit einer Zeit und einem Wert initialisiert wird.

Der Typ der value -Eigenschaft wird zum Zeitpunkt der Erstellung des Ereignisses festgelegt. Es kann entweder ein Int oder ein Double Primitiv sein.

Wie soll ich das in Swift implementieren?

Ich möchte in der Lage sein, ein neues Event Objekt wie folgt zu erstellen:

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

Ich habe dies gefunden Ich kann es nicht erkennen.

Ich habe mit so vielen Permutationen experimentiert und das Beste, was ich tun kann, ist

struct Event {
  let time: Date
  var value: EventValue? // This line 'requires arguments in <...>'
}

struct EventValue <T> {
  let value: T?
}
5
elight 18 Jän. 2019 im 22:37

4 Antworten

Beste Antwort

Wenn die Absicht besteht, einen (einzelnen) Event Typ mit einer EventValue -Eigenschaft zu haben, die entweder eine Ganzzahl oder einen doppelten Wert enthalten kann, dann Ein enum mit zugehörigen Werten würde diesem Zweck dienen:

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
Martin R 18 Jän. 2019 im 20:49

Da EventValue generisch ist, kann es nicht direkt als Typ einer Eigenschaft verwendet werden. * Sie müssen entweder direkt den Typparameter angeben, wodurch Sie einen Container erhalten, der immer eine bestimmte Vielfalt von {{X1} aufweist. }:

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

Oder machen Sie den Container auch generisch:

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

In beiden Fällen müssen Sie den Typ beim Erstellen einer Event nicht explizit angeben: let event = Event(time: Date(), value: EventValue(value: 40.3467)) Die Typinferenz füllt sie aus, wenn die Event selbst generisch ist.

(Nebenbei: Beachten Sie, dass Sie keine formale Einschränkung haben, dass T nur Double oder Int ist. Zum Beispiel ist auch let event = Event(time: Date(), value: EventValue(value: "123abc")) möglich. Wenn Sie dies streng möchten Vermeiden Sie dies. Die Antwort von Martin R bietet eine Lösung.)


* Ohne zu sehr ins Detail zu gehen, ist es eher ein "Ding, das einen Typ erzeugt" als ein Typ selbst.

4
jscs 18 Jän. 2019 im 22:50

Fügen Sie Ihrer Event -Struktur auch generische Parameter hinzu und verwenden Sie diesen Typ für den Parameter EventValue

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

Initialisieren Sie dann einfach EventValue, ohne den Typ anzugeben, da der Compiler es Ihnen ermöglicht, nur einen Wert zu übergeben, der der generischen Parametereinschränkung entspricht. Und da Ihr Parameter keine Einschränkungen hat, ist er gleich Any, sodass Sie einen beliebigen Typ übergeben können

let event = Event(time: Date.init(), value: EventValue(value: 40.3467))
3
Robert Dresler 18 Jän. 2019 im 19:54

Wenn Sie verschiedene Arten von EventValue unter demselben Event Typ unterstützen möchten (d. H. Keine Generika für Event), können Sie eine Protokollreferenz für EventValue speichern:

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

Der Nachteil des "Type Radiergummi" -Protokolls besteht darin, dass Sie die für das generische Argument von EventValue verwendeten Typinformationen verlieren. Möglicherweise können Sie dies jedoch über einige Hilfsmethoden im Protokoll umgehen. Beispielsweise können Sie einen gemeinsamen Nenner für alle T generischen Argumente verwenden, um auf die gemeinsame Funktionalität zuzugreifen (dies ist nur erforderlich, wenn Sie alle möglichen Typen umschalten möchten, die T annehmen kann).

0
Cristik 22 Jän. 2019 im 05:57