2015-08-06 12 views
8

Questo codice funziona come previsto. "intero è int" viene stampato in uscita.Swift "è" operatore con tipo memorizzato nella variabile

let integer = Int() 

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

voglio usare is operatore nello stesso modo in cui posso usare isKindOfClass metodo - la classe (o meglio digitare) memorizzato nella variabile. Si sarebbe simile a questa:

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

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

Purtroppo questo genererà un errore: Use of undeclared type 'IntType'.

IntType in if condizione ha anche un colore diverso (se lo si incolla al parco giochi) che in altri luoghi nel codice sorgente, il che suggerisce che (come dice il messaggio di errore) il suo essere trattato come un nome di classe (come IntType sarebbe una classe). Ma non lo è. Significa che l'operatore is non può essere utilizzato con le variabili sul lato destro?

Desidero utilizzare l'operatore is perché può confrontare non solo le classi, ma anche altri tipi.

Come posso verificare se il valore è di tipo che mi aspetto?


ho trovato soluzione sporca, ma in realtà è ben lungi dall'essere affidabile ...

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") 
} 

opere perfette, ma attenzione - causare questo è anche vero:

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

C'è un modo migliore?


Ok, ti ​​spiego ulteriormente ciò che voglio raggiungere. Ho un oggetto che gestisce istanze di istanze di classi generiche. A un certo punto devo scegliere una di quelle istanze di classi generiche basate sul tipo di generico. Esempio:

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 

Attualmente ho ToolInfo struct, perché per quanto ne so il tipo non è possibile ottenere approvata nel <> mentre un'istanza oggetto classe generica. Ma non riesco ancora a confrontarlo.

+0

ha anche pensato di implementare l'operatore ===, ma non lo risolve in modo elegante.un altro pensiero per avvolgerlo all'interno di una 'struct' come fanno gli optionals, ma non so se è accettabile per te. – rshev

+0

Non sono sicuro del motivo per cui è necessario archiviare la classe in una variabile, ma penso che le tipalità siano fatte per queste cose –

+0

Ragazzi ho aggiornato la domanda per mostrare il mio problema, forse alcuni di voi suggeriranno un altro modo per risolvere questo problema. @rshev come sarebbe? Potresti spiegarlo ulteriormente (con una struct) o mostrare qualche esempio di pseudo codice? – luleq

risposta

6

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

Corretto. Il lato destro di is deve essere hardcoded in fase di compilazione.

Se non è necessario il polimorfismo ei tipi sono tipi di classe, è possibile utilizzare === per confrontare l'dynamicType di un'istanza con un tipo di classe. Questo è l'unico modo per ottenere un tipo in una variabile sul lato destro di qualcosa in puro Swift.

+0

Hai detto" i tuoi tipi sono tipi di classe ". Ciò significa che è impossibile verificare il tipo di confronto di un tipo non di classe? Se potessi aggiornare la tua risposta con queste informazioni per renderla chiaramente visibile, accetterei questa risposta chiudendo questa domanda. – luleq

+0

"Ciò significa che è impossibile controllare il tipo di confronto del tipo non di classe?" Puoi confrontarli con 'is'. Ma non se ciò che è sul lato destro è una specie di tipo-in-a-variabile. Come ho detto nella mia risposta, il lato destro di 'is' deve essere hard-coded. Questo perché Swift è severo nel digitare; ha bisogno di sapere il tipo di tutto _at compile time_. – matt

-2

Ecco il mio esperimento con enum contenitore tipo (mi dispiace, scritto struct per errore nel commento precedente):

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 
} 

Si può fare qualcosa di simile nel progetto.

Problemi correlati