2016-09-19 3 views
4

Ich bin verwirrt über dynamische Überprüfung in Swift.Schnelle dynamische Typüberprüfung für Strukturen?

Insbesondere habe ich ein Weirdo Fall, wo ich möchte im Wesentlichen wissen, schreiben (oder zu finden) eine Funktion:

func isInstanceOf(obj: Any, type: Any.Type) -> Bool 

In Objective-C, das isKindOfClass ist, aber das wird nicht funktionieren, weil Any.Type enthält Swift-Strukturen, die keine Klassen sind (weniger NSObject Unterklassen).

Ich kann Swift is hier nicht verwenden, weil das einen hardcoded Typ erfordert.

Ich kann obj.dynamicType == type nicht verwenden, weil das Subklassen ignorieren würde.

Die Swift book scheint darauf hinzudeuten, dass diese Informationen verloren, und für structs überhaupt nicht zur Verfügung:

Klassen verfügen über zusätzliche Funktionen, die Strukturen nicht:

...

  • Typumwandlung ermöglicht Ihnen, den Typ einer Klasseninstanz zur Laufzeit zu prüfen und zu interpretieren.

(Auf der Type Casting Kapitel, sagt er "in Swift Typ Gießen mit dem IS und als Betreiber implementiert ist", so dass es eine breitere Definition von "type casting" als in other languages zu sein scheint.)

Allerdings kann es nicht sein, dass is/as nicht mit Strukturen arbeiten, da Sie Strings und Ints in eine [Any] setzen können, und sie später herausziehen, und verwenden Sie is String oder is Int, um herauszufinden, was sie waren . Das Type Casting Kapitel des Swift Books macht genau das!

Gibt es etwas, das so leistungsstark ist wie isKindOfClass, aber für alle Swift-Instanzen? Diese Information muss zur Laufzeit noch existieren, oder?

+0

FYI, mehr Informationen zu dem, was Sie eigentlich tun möchten, wäre hilfreich :) – PeejWeej

+0

Ich denke, ich habe ziemlich genau destilliert, was ich versuche zu tun. Ich habe einige Eingaben, die einen Typ enthalten, und ich möchte (zum Beispiel) eine '[Any]' - Sammlung nur für Mitglieder dieses Typs filtern. Ich kann es mit einer großen if-else-Kette oder einer switch-Anweisung machen, die alle möglichen Typen auflistet, aber das ist schrecklich hässlich (ganz zu schweigen von redundant und nicht wiederverwendbar). Außerdem versuche ich zu lernen, wie das alles tatsächlich in der Erinnerung funktioniert, denn wie geschrieben, scheint das Swift-Sprachbuch selbst widersprüchlich zu sein. –

Antwort

4

Eigentlich können Sie is Operator verwenden.

Verwenden Sie den Operator type check (is), um zu überprüfen, ob eine Instanz einen bestimmten Unterklasse-Typ aufweist. Der Typüberprüfungsoperator gibt "true" zurück, wenn die Instanz von diesem Unterklasse-Typ ist, und false, wenn dies nicht der Fall ist.

Da struct nicht subclassed werden, is ist garantiert, konsequent sein, wenn sie beispielsweise von Struktur angewendet, weil es auf sie statischen Typ überprüfen wird, und für die Klassen wird es den dynamischen Typ in Laufzeit abfragen.

func `is`<T>(instance: Any, of kind: T.Type) -> Bool{ 
    return instance is T; 
} 

Diese Arbeit für beide, struct und class.

+0

Das ist eine clevere Lösung, aber ich bin immer noch verwirrt über Swift tippen. Was bedeutet das Swift-Buch, wenn es ausdrücklich besagt, dass "Typ-Casting" nicht mit Strukturen funktioniert (und Typ-Casting als das, was Sie mit den "is" - und "as" -Schlüsselwörtern tun), wenn Sie es mit Strukturen verwenden können Alles gut? –

+1

* ist * ist eigentlich kein Typcasting-Operator, ist ein reflektorischer Operator, der eine kleine Typinformation einer Instanz gibt, * wie * kann in struct verwendet werden, aber nicht wie bei Klassen, mit struct kann man es verwenden, wenn Die Variable wird als * Any * deklariert. Sie enthält eine Instanz von Struktur A und Sie möchten sie wieder in A umwandeln. Und in Klassen können Sie es verwenden, um ein Objekt in eine Basisklasse und möglicherweise in Unterklassen zu verwandeln, was mit struct nicht möglich ist. Vielleicht ist das der Grund, warum das Buch sagt, dass * as * nicht auf Strukturen funktioniert. – xhamr

+0

Strukturen können nicht unterklassiert werden, aber sie können sich an Protokolle halten, daher kann eine Struktur nicht in einen anderen Strukturtyp umgewandelt werden, da dies nicht möglich ist, aber es ist möglich, dass sie einem Protokoll entsprechen und daher in ein Protokoll umgewandelt werden können. In diesem Fall "Any" – PeejWeej

1

Wie bereits erwähnt, sollte/as sollte gut mit Strukturen funktionieren.Andere Ecken Fälle können in der Regel mit generischen Funktionen, etwa wie folgt gemacht werden:

Keine Ahnung, ob dies zu Ihrem spezifischen Anwendungsfall passt.

Im Allgemeinen sollten Sie bedenken, dass Swift (derzeit) den Typ von allem zur Kompilierzeit wissen muss. Wenn Sie den spezifischen Typ, der an eine Funktion übergeben oder als Variable festgelegt wird, nicht definieren können, wird auch der Compiler nicht.

+0

Diese Funktion ist hilfreich (und clever), aber ich bin mir nicht sicher, was Ihr letzter Absatz bedeutet. In Ihrem Beispiel hat 'thing' den Typ' Any' deklariert, aber die Laufzeitumgebung muss mehr darüber wissen, da sie zur Laufzeit 'item (item: isType:)' aufruft und ihren Laufzeittyp überprüft. Wenn ich Benutzereingaben entweder als Int oder als String genommen habe und sie an diese Funktion übergeben habe, sagt sie mir tatsächlich den Typ davon. –

+0

Es wird Ihnen den Typ nicht sagen, aber Sie könnten überprüfen, ob es eine Zeichenfolge oder ein int war. Denken Sie daran, dass "Any" einfach ein Protokoll ist, an das sich structs/classes halten, also haben Variablen vom Typ "Any" keinen definierten Wert. – PeejWeej

+0

Teil von dem, was ich mit dem letzten Teil meinte, ist, dass in meinem Beispiel alle Typen in den Funktionssignaturen im Code definiert sind. Es verwendet Generics, um etwas Dynamik im Code zu erlauben, aber zur Kompilierzeit sind die genauen Typen für alle Verwendungen von item bekannt (isType :) – PeejWeej

Verwandte Themen