2015-08-06 15 views
8

Dieser Codeabschnitt funktioniert wie erwartet. "integer is int" wird in Ausgabe ausgegeben.Swift "ist" -Operator mit Typ in Variable gespeichert

let integer = Int() 

if integer is Int { 
    println("integer is int") 
} 
else { 
    println("integer is not int") 
} 

Ich mag is Betreiber in der gleichen Art und Weise verwenden, wie ich isKindOfClass Methode verwenden kann - mit Klasse (oder eher Typ) in Variablen gespeichert. Es würde wie folgt aussehen:

let integer = Int() 
let intType : Any = Int.self 

if integer is intType { 
    println("Integer is int") 
} 
else { 
    println("Integer is not int") 
} 

Leider dies zu einem Fehler: Use of undeclared type 'IntType'.

IntType in if Zustand hat auch eine andere Farbe (wenn Sie es zum Spielplatz Paste) als an anderen Orten im Quellcode, was darauf hindeutet, dass (wie die Fehlermeldung sagt) sein als Klassenname behandelt wird (wie IntType wären eine Klasse). Aber es ist nicht. Es bedeutet, dass is Operator nicht mit Variablen auf der rechten Seite verwendet werden kann?

Ich möchte is Operator verwenden, weil es nicht nur Klassen, sondern auch andere Arten vergleichen kann.

Wie kann ich prüfen, ob der Wert den Typ hat, den ich erwarte?


fand ich schmutzige Lösung, aber es ist wirklich weit davon entfernt zuverlässig zu sein ...

let integer = Int() 
let intType : Any = Int.self 

func ==(left: Any, right: Any) -> Bool { 
    let leftString = "\(left)" 
    let rightString = "\(right)" 
    return leftString == rightString 
} 

if (integer.dynamicType as Any) == intType { 
    println("true") 
} 
else { 
    println("false") 
} 

funktioniert perfekt, aber vorsichtig sein - dazu führen, dies ist auch wahr:

if (integer.dynamicType as Any) == ("Swift.Int" as Any) { 
    println("true") 
} 
else { 
    println("false") 
} 

Gibt es einen besseren Weg?


Ok, ich werde weiter erklären, was ich erreichen möchte. Ich habe ein Objekt, das Instanzen von generischen Klasseninstanzen verwaltet. Irgendwann muss ich eine dieser generischen Klasseninstanzen auswählen, die auf dem generischen Typ basieren. Beispiel:

class GenericClass<T> {} 

struct ToolInfo { 
    let tool : AnyObject 
    let jobType : Any 
} 

class Manager { 
    var tools = Array<ToolInfo>() 

    func pickToolForTheJob(job : Any) -> AnyObject { 
     return tools.magicMethodWhichReturnProperTool() 
    } 
} 

let viewTool = GenericClass<UIView>() 
let rectangleTool = GenericClass<CGRect>() 

let manager = Manager() 
manager.tools.append(ToolInfo(tool: viewTool, jobType: UIView.self)) 
manager.tools.append(ToolInfo(tool: rectangleTool, jobType: CGRect.self)) 

manager.pickToolForTheJob(UIView()) // i want to get viewTool here 
manager.pickToolForTheJob(CGRect()) // i want to get rectangleTool here 

Zur Zeit habe ich ToolInfo Struktur, denn soweit ich weiß nicht, seine mögliche Art in <> weitergegeben zu bekommen, während generische Klasse Objekt zu erhalten. Aber ich kann es immer noch nicht vergleichen.

+0

dachte auch über die Implementierung === Operator, aber es löst es nicht elegant.ein weiterer Gedanke, es in eine 'struct' zu integrieren, wie es Optionals tun, aber ich weiß nicht, ob es für dich akzeptabel ist. – rshev

+0

Nicht sicher, warum Sie Klasse in eine Variable speichern müssen, aber ich denke, dass Typalias für diese Dinge gemacht werden –

+0

Jungs Ich habe Frage aktualisiert, um mein Problem zu zeigen, vielleicht einige von Ihnen schlagen andere Wege vor, um dieses Problem zu lösen. @rshev wie würde es aussehen? Kannst du es bitte weiter erklären (mit einer Struktur) oder ein Pseudocode-Beispiel zeigen? – luleq

Antwort

6

It means that is operator cannot be used with variables on the right side?

Korrekt. Die rechte Seite von is muss zur Kompilierungszeit fest codiert sein. Wenn Sie keine Polymorphie benötigen und Ihre Typen Klassentypen sind, können Sie === verwenden, um die dynamicType einer Instanz mit einer Klassenart zu vergleichen. Das ist der einzige Weg, wie Sie eine Art-in-a-Variable auf der rechten Seite von etwas in reinem Swift bekommen.

+0

Sie sagten" Ihre Typen sind Klassentypen ". Dies bedeutet, dass es unmöglich ist, den Vergleichstyp des Nicht-Klassen-Typs zu prüfen. Wenn Sie Ihre Antwort mit dieser Information aktualisieren könnten, um sie deutlich sichtbar zu machen, würde ich diese Antwort als Schließen dieser Frage akzeptieren. – luleq

+0

"Dies bedeutet, dass es nicht möglich ist, den Vergleichstyp des Nicht-Klassen-Typs zu prüfen?" Sie können sie mit "ist" vergleichen. Aber nicht, wenn auf der rechten Seite eine Art Typ-in-Variable ist. Wie ich in meiner Antwort gesagt habe, muss die rechte Seite von "ist" fest codiert sein. Dies liegt daran, dass Swift das Tippen streng beherrscht; es muss den Typ von allem _at compile time_ kennen. – matt

-2

Hier ist mein Versuch mit enum artigen Behältern (sorry, in dem Kommentar früheren struct versehentlich geschrieben):

enum TypeContainer { 
    case SomeInt(Int) 
    case SomeString(String) 
    case SomeBool(Bool) 

    init(int: Int) { 
     self = .SomeInt(int) 
    } 

    init(string: String) { 
     self = .SomeString(string) 
    } 

    init(bool: Bool) { 
     self = .SomeBool(bool) 
    } 
} 

let a = TypeContainer(string: "123") 
let b = TypeContainer(int: 88) 
let c = TypeContainer(bool: true) 

switch a { 
case .SomeInt(let i): 
    println(i) 
case .SomeString(let s): 
    println(s) 
case .SomeBool(let b): 
    println(b) 
default: 
    break 
} 

Sie können in Ihrem Projekt so etwas tun.