2016-08-19 4 views
4

eine Klasse Gegeben:Swift generische Funktion als varaible gespeichert

class First<T> { 

} 

und ein Verfahren des First Class:

func second<U>(closure: (value: T) -> U) { 

} 

Wie kann ich die Schließung als Argument übergeben speichern, um second so dass ich zu einem späteren Zeitpunkt anrufen?

+0

Wahrscheinlich verwandt: http://stackoverflow.com/questions/25401584/generics-as-parameters-to-a-closure-in-swift –

Antwort

1

Sie müßten U in der Klasse statt zu erklären, so dass Sie einen Typen für die Lagerung haben:

class First<T,U> { 
    var f : ((T) -> U)! = nil 
    func second(closure: @escaping (T) -> U) { 
     self.f = closure 
    } 
} 
+1

Das ist Swift 3: Xcode 8, Seed 6. Beachten Sie, dass Ihr 'Wert: 'ist jetzt illegal und das '@ escaping' wird benötigt, um anzuzeigen, dass diese Funktion nicht für die sofortige Ausführung gedacht ist. – matt

+0

Ärgerlich scheint dies der einzige Weg zu sein, es richtig zu machen –

1

nur eine Art von Typ die Funktion second Arbeit für Sie ist gut genug, wenn mit, dann ist Matts Antwort gut.

class First<T, U> { 
    typealias ClosureType = (value: T) -> U 
    var savedClosure: ClosureType? = nil 
    func second(closure: ClosureType) { 
     savedClosure = closure 
    } 
} 

Das beantwortet Ihre Frage nicht wie angegeben!

Die Sache ist: Sie können einen Wert eines unbekannten Typs nicht speichern. Aber! Wenn der Typ einem bekannten Protokoll entspricht, können Sie ihn speichern.

protocol P {} 

class First<T> { 
    typealias ClosureType = (value: T) -> P 
    var savedClosure: ClosureType? = nil 
    func second<U: P>(closure: (value: T) -> U) { 
     savedClosure = closure 
    } 
} 

Das Protokoll selbst protocol<> „kein Protokoll an all“ sein könnte, die das Schlüsselwort Any typealiased wird.

class First<T> { 
    typealias ClosureType = (value: T) -> Any 
    var savedClosure: ClosureType? = nil 
    func second<U>(closure: (value: T) -> U) { 
     savedClosure = closure 
    } 
} 

Aber wir wissen nicht wirklich, was Sie tun wollen, so gibt es mehrere Antworten auf Ihre Frage ... zum Beispiel, vielleicht wollten Sie für jeden Typ einen separaten Verschluss speichern?

class First<T> { 
    typealias ClosureType = (value: T) -> Any 
    var savedClosures = [String: ClosureType]() 
    func second<U>(closure: (value: T) -> U) { 
     savedClosures[String(U)] = closure 
    } 
} 

Wie dem auch sei, die eigentliche Frage ist: „Haben Sie das wirklich tun müssen, ist es eine einfache Änderung, die Sie tun können, vermeidet diese Notwendigkeit?“

+0

Der Grund, warum ich eine Schließung mit zwei Generika in speichern möchte, ist einige Mapping-Funktionalität zur Verfügung zu stellen. I.e. Karten "T" bis "U". Das Problem mit Ihrer Lösung besteht darin, dass jedes Mal, wenn ich eine 'string' ID an ein 'int' mappen möchte, meine eigene Version von string implementieren muss, die einem Protokoll vom Typ' P' folgt. Upvote für Kreativität obwohl! –

+0

Sie können eine leere Erweiterung 'extension String: P {}' verwenden, aber Sie müssen nicht, wenn Sie 'Any' verwenden, da" alle Typen implizit damit übereinstimmen ". –

Verwandte Themen