2016-06-27 6 views
2

ich eine Funktion wie diese implementiert werden sollen:Swift: Typ als Argument senden und der Typ einer Variablen vergleichen es

protocol Base { 
    var value: Int { get set } 
} 
class ObjectTypeA: Base { 
    var value: Int = 0 
} 
class ObjectTypeB: Base { 
    var value: Int = 1 
} 

var objects: [Base] = [ObjectTypeA(), ObjectTypeB()] 
func updatePropertyForType(type: Base.Type, value: Int) { 
    objects.filter({ $0 is type }).forEach { // <<< ERROR IS HERE 
     var object = $0 
     object.value = value 
    } 
} 
updatePropertyForType(ObjectTypeB.self, value: 10) 

Aber es ist ein Fehler:

'type' is not a type 

Bitte, hilf mir repariere es.

+0

Mögliche Duplikat von [Wie zwei Instanzen der gleichen Klasse/Typ in swift sind zu überprüfen] (http://stackoverflow.com/questions/24161622/how-to-check-two-instances-are-the-same-class-type-in-swift) – Daniel

+0

Wie schon erwähnt - "Das ist eigentlich kein reiner Swift "Ich würde gerne eine richtige Koschere finden, um dieses Beispiel zu lösen. – adnako

+0

@simpleBob, Könnten Sie bitte, bitte, meinen Code reparieren, um mir zu zeigen, was meinst du - "bereits beantwortet"? Ich kann dort keine Antwort finden. – adnako

Antwort

1

Wie die anderen Antworten haben entzog sich an, Sie nicht Meta-Typen mit is verwenden können. Eine bessere Lösung wäre jedoch, einfach Generika zu verwenden. Dies ermöglicht Swift den Typ, den Sie in die Funktion übergeben zu schließen, so dass Sie es schreiben, wie:

protocol Base : class { 
    var value: Int { get set } 
} 

class ObjectTypeA: Base { 
    var value: Int = 0 
} 
class ObjectTypeB: Base { 
    var value: Int = 1 
} 

var objects: [Base] = [ObjectTypeA(), ObjectTypeB()] 

func updateElements<T:Base>(ofType type: T.Type, withValue value: Int) { 
    objects.filter{ $0 is T }.forEach{ $0.value = value } 
} 

updateElements(ofType: ObjectTypeB.self, withValue: 10) 

Sie auch zu ermöglichen Swift wollen werden Ihre Base Protokollklasse gebunden (: class) machen, um zu behandeln Base typisierte Instanzen als Referenztypen (damit Sie $0.value = value tun können).

Ihre vorherigen Code:

var object = $0 
object.value = value 

würde für Referenztypen gearbeitet haben, aber nicht für Werttypen - wie object hier ist einfach eine Kopie von $0, so werden alle Mutationen nicht in widerspiegeln das Array. Daher sollten Sie Ihr Protokoll mit Anmerkungen versehen, um zu verdeutlichen, dass Ihr Protokoll nicht für die Verwendung mit Werttypen ausgelegt ist.

Wenn Sie wollen in der Lage sein, Werttypen zu handhaben, sollten Sie mit map stattdessen berücksichtigen:

func updateElements<T:Base>(ofType type: T.Type, withValue value: Int) { 
    objects = objects.map { 
     var object = $0 
     if object is T { 
      object.value = value 
     } 
     return object 
    } 
} 
+0

Danke, ich habe nicht über Generika nachgedacht! Leider kann ich das ** Base ** -Protokoll nicht ändern, es ist ein Drittanbieter-Framework. Ich weiß über Wert- und Referenztypen Bescheid, aber ich danke Ihnen, dass Sie es öffentlich gemacht haben. – adnako

+0

@adnako Ah okay, ich nehme an, du könntest ein Zwischenprotokoll erstellen, das sowohl an die Klasse gebunden ist als auch 'Base' entspricht - und dann deine Klassen anpassen und es als deinen Array-Typ verwenden, obwohl das den Wert wert sein mag oder nicht extra Aufwand. Freue mich zu helfen :) – Hamish

2

Siehe this answer:

protocol Base: AnyObject { 
    var value: Int { get set } 
} 
class ObjectTypeA: Base { 
    var value: Int = 0 
} 
class ObjectTypeB: Base { 
    var value: Int = 1 
} 

var objects: [Base] = [ObjectTypeA(), ObjectTypeB()] 
func updatePropertyForType(type: Base.Type, value: Int) { 
    objects.filter({let item = $0; return type === item.dynamicType }).forEach { 
     $0.value = value 
    } 
} 

nennen es mit:

updatePropertyForType(ObjectTypeA.self, value: 3) 
+0

Danke, aber jetzt muss ich ein dummes Objekt erstellen, um diese Funktion zu verwenden, anstatt einen Typ zu senden. Gibt es eine bessere Lösung? – adnako

+0

@adnako Ich habe die Antwort aktualisiert – Daniel

+0

Ja, ich habe eine Lösung gefunden, danke. Nur eine kleine Bemerkung - ** $ 0.value = value ** ist falsch, weil eine ** value ** Eigenschaft unveränderlich ist. – adnako

1

Aber dieser Code funktioniert gut.

protocol Base { 
    var value: Int { get set } 
} 
class ObjectTypeA: Base { 
    var value: Int = 0 
} 
class ObjectTypeB: Base { 
    var value: Int = 1 
} 

var objects: [Base] = [ObjectTypeA(), ObjectTypeB()] 
func updatePropertyForType(type: Base.Type, value: Int) { 
    objects.filter({ object in 
     let result = object.dynamicType == type 
     return result 
    }).forEach { 
     var object = $0 
     object.value = value 
    } 
} 
updatePropertyForType(ObjectTypeB.self, value: 10) 
print(objects)