Ich habe eine generische struct
, die jede Art annimmt, und eine Funktion:Wie funktioniert die Standardfunktion in Swift, abhängig vom generischen Typ?
struct Test<T> {
func makeSomething() -> T? {
print("Default implementation")
return nil
}
}
ich auch ein Protokoll haben, die eine statische Methode enthält, die eine Instanz von sich selbst zurückgibt:
protocol TestProtocol {
static func defaultValue() -> Self
}
ich will makeSomething
Funktion, die spezialisiert werden soll, wenn T
TestProtocol
entspricht. Beispiel Nutzung:
struct TestItem: TestProtocol {
static func defaultValue() -> TestItem {
return TestItem()
}
}
let normalTest: Test<String> = Test()
let normalReturn = normalTest.makeSomething() // Should use default, returns nil.
let specialTest: Test<TestItem> = Test()
let specialReturn = specialTest.makeSomething() // Should use specialised, returns `TestItem`.
kann ich denke an ein paar Möglichkeiten, dies zu tun, aber keiner von ihnen arbeiten (oder ich weiß nicht, wie man sie richtig implementieren).
Option 1
eine Typ-constrained Erstellen Erweiterung für Test
:
extension Test where T : TestProtocol {
func makeSomething() -> T? {
print("Special implementation")
return T.defaultValue()
}
}
Problem: Versuch, die makeSomething
Funktion führt zu einem Fehler zu verwenden: ambiguous use of 'makeSomething()'
. Ich verstehe, warum der Fehler auftritt; nur weil ich eine spezialisierte Funktion erstelle, bedeutet das nicht, dass die Standardfunktion weniger gültig ist und daher nicht weiß, welche Funktion verwendet werden soll.
Es könnte auch möglich sein, die Standardimplementierung in eine Erweiterung zu bewegen, wie gut, aber es wäre Typ Zwänge haben muß, die entlang der Linien etwas sagen ‚jede Art, die nicht-TestProtocol
entsprechen‘, und Soweit ich weiß, ist das nicht möglich.
Option 2
Spezialteile auf die makeSomething
Funktion hinzufügen, so dass er sein Verhalten von der Art der T
abhängig ändert:
func makeSomething() -> T? {
if let specialType = T.self as? TestProtocol.Type {
print("Special implementation")
return specialType.defaultValue()
} else {
print("Default implementation")
return nil
}
}
Problem: Wie erwartet, das nicht funktioniert, seit specialType
ist jetzt vom Typ TestProtocol.Type
und nicht T
, so bekomme ich den Fehler: cannot convert return expression of type 'TestProtocol' to return type 'T?'
. Ich weiß nicht, wie man den Compiler informiert, dass T
in diesem Fall ein TestProtocol
ist.
Das eigentliche Problem, das ich habe, ist komplexer, aber ich denke, dass dies vereinfacht und das Problem, das ich habe, richtig darstellt. Gibt es eine Möglichkeit, in Abhängigkeit von der Übereinstimmung von T
innerhalb der oben genannten Einschränkungen Standard und spezialisierte Funktionalität zu haben?
Danke für Ihre Antwort! Ich hatte auch daran gedacht, in Option 1 eine Besetzung zu machen; Es funktioniert, aber wie du selbst, ich dachte, es war nicht sehr elegant. Ich denke, ich akzeptiere wahrscheinlich, dass es für den Moment die beste Lösung ist, dies über Protokolle zu tun. Vielleicht wird es in Zukunft bessere Methoden geben! – Robert
@Robert Glücklich zu helfen! Swift ist noch relativ jung und entwickelt sich rasant weiter. Ich bin mir sicher, dass es in Zukunft bessere Lösungen geben wird :) – Hamish