Swift Equatable auf einem Protokoll

9

Ich denke nicht, dass das gemacht werden kann, aber ich werde trotzdem fragen. Ich habe ein Protokoll:

%Vor%

Und eine Klasse:

%Vor%

Im Rest meines Codes beziehe ich mich auf alles unter Verwendung des Protokolls X. In diesem Code möchte ich etwas tun können wie:

%Vor%

Das Problem ist, dass wenn ich versuche, Equatable zu implementieren:

%Vor%

Die Idee zu versuchen, die Verwendung von == zuzulassen, während die Implementierungen hinter dem Protokoll versteckt werden.

Swift mag das jedoch nicht, weil Equatable Self references hat und es mir nicht länger erlaubt, es als Typ zu verwenden. Nur als generisches Argument.

Hat jemand also einen Weg gefunden, einen Operator auf ein Protokoll anzuwenden, ohne dass das Protokoll als Typ unbrauchbar wird?

    
drekka 09.02.2017, 06:55
quelle

6 Antworten

5

Der Grund, warum Sie zweimal darüber nachdenken sollten, ein Protokoll konform zu Equatable zu haben, ist, dass es in vielen Fällen keinen Sinn ergibt. Betrachten Sie dieses Beispiel:

%Vor%

Sie anspielen im Rahmen der Umsetzung von == Überprüfung zu geben, aber das Problem ist, dass Sie keine Informationen haben über eine der beiden Arten über sie zu sein Pet s und Sie wissen nicht, all die Dinge, die ein% sein könnten co_de% (vielleicht fügen Sie später Pet und Bird hinzu). Wenn Sie dies wirklich benötigen, können Sie mit einem anderen Ansatz modellieren, wie Sprachen wie C # die Gleichheit implementieren, indem Sie beispielsweise Folgendes tun:

%Vor%

An diesem Punkt, wenn Sie wirklich wollten, könnten Sie Rabbit implementieren, ohne == zu implementieren:

%Vor%

Eine Sache, auf die Sie in diesem Fall achten sollten, ist die Vererbung. Weil Sie einen Erbtyp ablehnen und die Informationen löschen könnten, die Equatable nicht logisch erscheinen lassen.

Der beste Weg, um zu gehen, ist, nur Gleichheit auf der Klasse / Struktur selbst zu implementieren und einen anderen Mechanismus für Typprüfung zu verwenden.

    
Scott H 09.02.2017 09:48
quelle
3

vielleicht wird das für Sie hilfreich sein:

%Vor%     
Konstantin Kryzhanovsky 09.02.2017 08:15
quelle
3

Wenn Sie Equatable für ein Protokoll direkt implementieren, ist es nicht länger als Typ verwendbar, was den Zweck der Verwendung eines Protokolls zunichtemacht. Selbst wenn Sie == functions nur bei Protokollen ohne Equatable -Konformität implementieren, können die Ergebnisse fehlerhaft sein. Siehe diesen Beitrag in meinem Blog für eine Demonstration dieser Probleme:

Ссылка

Der Ansatz, den ich am besten finde, ist das Löschen von Typen. Dies ermöglicht == Vergleiche für Protokolltypen (in Type-Radiergummis eingeschlossen). Es ist wichtig zu beachten, dass, während wir weiter auf Protokollebene arbeiten, die tatsächlichen == Vergleiche an die zugrunde liegenden konkreten Typen delegiert werden, um korrekte Ergebnisse sicherzustellen.

Ich habe einen Typenradierer mit Ihrem kurzen Beispiel erstellt und am Ende etwas Testcode hinzugefügt. Ich habe eine Konstante vom Typ String zum Protokoll hinzugefügt und zwei konforme Typen erstellt (Strukturen sind am einfachsten zu Demonstrationszwecken), um die verschiedenen Szenarien testen zu können.

Eine ausführliche Erläuterung der verwendeten Löschmethode finden Sie in Teil 2 des obigen Blogposts:

Ссылка

Der folgende Code sollte den Gleichheitsvergleich unterstützen, den Sie implementieren wollten. Sie müssen den Protokolltyp nur in eine Typlöserinstanz umbrechen.

%Vor%

Beachten Sie, dass Sie, da der Typradierer dem Protokoll entspricht, Instanzen des Typs radiergummi überall dort verwenden können, wo eine Instanz des Protokolltyps erwartet wird.

Hoffe, das hilft.

    
Khawer Khaliq 12.10.2017 21:17
quelle
2

Nicht sicher, warum Sie alle Instanzen Ihres Protokolls mit Equatable übereinstimmen müssen, aber ich bevorzuge es, Klassen ihre Gleichheitsverfahren implementieren zu lassen.

In diesem Fall würde ich das Protokoll einfach lassen:

%Vor%

Wenn Sie möchten, dass ein Objekt, das mit MyProtocol übereinstimmt, auch Equatable ist, können Sie MyProtocol & Equatable als Typbeschränkung verwenden:

%Vor%

Auf diese Weise können Sie Ihre Spezifikation klar halten und Unterklassen ihre Gleichheits-Methode nur bei Bedarf implementieren lassen.

    
redent84 09.02.2017 11:28
quelle
2

Ich rate immer noch davon ab, == mit Polymorphismus zu implementieren. Es ist ein bisschen wie ein Code-Geruch. Wenn Sie dem Framework-Benutzer etwas geben wollen, mit dem er die Gleichheit testen kann, dann sollten Sie wirklich eine struct , nicht eine protocol verkaufen. Das heißt nicht, dass es nicht die protocol s sein kann, die die struct s verkaufen:

%Vor%

Ich denke, dass dies Ihre Absicht effizienter kommuniziert, was im Grunde "Sie haben diese Dinge und Sie wissen nicht, ob sie die gleichen Dinge sind, aber Sie wissen, dass sie die gleichen Eigenschaften haben und Sie können diese testen Eigenschaften sind die gleichen. " Das ist ziemlich ähnlich wie ich das Money Beispiel implementieren würde.

    
Scott H 11.02.2017 04:16
quelle
1

Sie müssen eine Protokollerweiterung eingeschränkt in Ihren Klassentyp implementieren. Innerhalb dieser Erweiterung sollten Sie den Operator Equatable implementieren.

%Vor%

Aber ich empfehle Ihnen, die Operator-Implementierung zu Ihrer Klasse hinzuzufügen. Halten Sie es einfach; -)

    
Adolfo 09.02.2017 07:15
quelle

Tags und Links