Das Buch sagt, dass "Funktionen und Verschlüsse Referenztypen sind". Wie finden Sie heraus, ob die Referenzen gleich sind? == und === funktionieren nicht.
func a() { }
let å = a
let b = å === å // Could not find an overload for === that accepts the supplied arguments
MyClass.self
å
Hinweisesa
ist wirklich interessant. Gibt es eine Konvention, die Sie hier erkunden? (Ich weiß nicht, ob es mir wirklich gefällt oder nicht; aber es scheint sehr leistungsfähig zu sein, insbesondere in der reinen funktionalen Programmierung.)Antworten:
Chris Lattner schrieb in den Entwicklerforen:
https://devforums.apple.com/message/1035180#1035180
Dies bedeutet, dass Sie nicht einmal versuchen sollten, Abschlüsse auf Gleichheit zu vergleichen, da Optimierungen das Ergebnis beeinflussen können.
quelle
Ich habe viel gesucht. Es scheint keine Möglichkeit zum Vergleich von Funktionszeigern zu geben. Die beste Lösung besteht darin, die Funktion oder den Abschluss in einem hashbaren Objekt zu kapseln. Mögen:
quelle
Einfachste Weg ist , den Blocktyp bezeichnen , wie
@objc_block
, und jetzt können Sie es zu einem ANYOBJECT gegossen , die mit vergleichbar ist===
. Beispiel:quelle
Ich habe auch nach der Antwort gesucht. Und ich habe es endlich gefunden.
Was Sie brauchen, ist der eigentliche Funktionszeiger und sein im Funktionsobjekt versteckter Kontext.
Und hier ist die Demo:
In den folgenden URLs erfahren Sie, warum und wie es funktioniert:
Wie Sie sehen, kann nur die Identität überprüft werden (der 2. Test ergibt
false
). Das sollte aber gut genug sein.quelle
Dies ist eine großartige Frage, und obwohl Chris Lattner diese Funktion absichtlich nicht unterstützen möchte, kann ich, wie viele Entwickler, auch meine Gefühle aus anderen Sprachen nicht loslassen, in denen dies eine triviale Aufgabe ist. Es gibt viele
unsafeBitCast
Beispiele, von denen die meisten nicht das vollständige Bild zeigen. Hier ist ein detaillierteres :Der interessante Teil ist, wie schnell SwfBlock frei in ObjBlock umgewandelt wird, aber in Wirklichkeit haben zwei gegossene SwfBlock-Blöcke immer unterschiedliche Werte, während ObjBlocks dies nicht tun. Wenn wir ObjBlock in SwfBlock umwandeln, passiert ihnen dasselbe, sie werden zu zwei verschiedenen Werten. Um die Referenz zu erhalten, sollte diese Art des Gießens vermieden werden.
Ich verstehe das ganze Thema immer noch, aber eine Sache, die ich mir noch gewünscht habe, ist die Fähigkeit,
@convention(block)
Klassen- / Strukturmethoden zu verwenden. Deshalb habe ich eine Feature-Anfrage eingereicht, die eine Abstimmung erfordert oder erklärt, warum dies eine schlechte Idee ist. Ich habe auch das Gefühl, dass dieser Ansatz insgesamt schlecht sein könnte. Wenn ja, kann jemand erklären, warum?quelle
Struct S { func f(_: Int) -> Bool }
, haben Sie tatsächlich eine Funktion vom Typ,S.f
die Typ hat(S) -> (Int) -> Bool
. Diese Funktion kann gemeinsam genutzt werden. Es wird ausschließlich durch seine expliziten Parameter parametrisiert. Wenn Sie es als Instanzmethode verwenden (entweder indem Sie denself
Parameter implizit binden, indem Sie die Methode für ein Objekt aufrufen, z. B.S().f
indem Sie es explizit binden, z. B.S.f(S())
), erstellen Sie ein neues Abschlussobjekt. Dieses Objekt speichert einen Zeiger aufS.f
(der gemeinsam genutzt werden kann), but also to your instance (
self, the
S () `).S
. Wenn die Gleichheit des Abschlusszeigers möglich wäre, wären Sie überrascht zu entdecken, dass diess1.f
nicht derselbe Zeiger ist wies2.f
(weil eines ein Abschlussobjekt ist, das aufs1
und verweistf
, und das andere ein Abschlussobjekt ist, das aufs2
und verweistf
).Hier ist eine mögliche Lösung (konzeptionell die gleiche wie die Antwort "tuncay"). Der Punkt besteht darin, eine Klasse zu definieren, die einige Funktionen einschließt (z. B. Befehl):
Schnell:
Java:
quelle
Nun, es sind 2 Tage vergangen und niemand hat eine Lösung gefunden, also werde ich meinen Kommentar in eine Antwort ändern:
Soweit ich das beurteilen kann, können Sie die Gleichheit oder Identität von Funktionen (wie in Ihrem Beispiel) und Metaklassen (z. B.) nicht überprüfen
MyClass.self
:Aber - und das ist nur eine Idee - ich kann nicht anders, als zu bemerken, dass die
where
Klausel in Generika in der Lage zu sein scheint, die Gleichheit der Typen zu überprüfen. Vielleicht können Sie das nutzen, zumindest um die Identität zu überprüfen?quelle
Keine allgemeine Lösung, aber wenn man versucht, ein Listener-Muster zu implementieren, habe ich während der Registrierung eine "ID" der Funktion zurückgegeben, damit ich sie später abmelden kann (was eine Art Problemumgehung für die ursprüngliche Frage darstellt Für den Fall "Zuhörer" kommt es normalerweise darauf an, die Funktionen auf Gleichheit zu überprüfen, was nach anderen Antworten zumindest nicht "trivial" ist.
Also so etwas wie das:
Jetzt müssen Sie nur noch die
key
von der Funktion "register" zurückgegebene Funktion speichern und beim Aufheben der Registrierung übergeben.quelle
Meine Lösung bestand darin, Funktionen in eine Klasse zu verpacken, die NSObject erweitert
quelle
Ich weiß, dass ich diese Frage sechs Jahre zu spät beantworte, aber ich denke, es lohnt sich, die Motivation hinter der Frage zu betrachten. Der Fragesteller kommentierte:
Ich denke, der Fragesteller möchte eine Rückrufliste wie folgt führen:
Aber wir können nicht so schreiben
removeCallback
, weil==
es für Funktionen nicht funktioniert. (Auch nicht===
.)Hier ist eine andere Möglichkeit, Ihre Rückrufliste zu verwalten. Geben Sie ein Registrierungsobjekt von zurück
addCallback
und entfernen Sie den Rückruf mithilfe des Registrierungsobjekts. Hier im Jahr 2020 können wir die KombinateAnyCancellable
als Registrierung verwenden.Die überarbeitete API sieht folgendermaßen aus:
Wenn Sie jetzt einen Rückruf hinzufügen, müssen Sie ihn nicht mehr behalten, um ihn
removeCallback
später weiterzuleiten . Es gibt keineremoveCallback
Methode. Stattdessen speichern Sie dieAnyCancellable
und rufen ihrecancel
Methode auf, um den Rückruf zu entfernen. Noch besser, wenn Sie dieAnyCancellable
Eigenschaft in einer Instanz speichern , bricht sie sich automatisch ab, wenn die Instanz zerstört wird.quelle