2017-08-31 2 views
2

ich eine Equatable KlasseANYOBJECT versuchen werfen

class Item: Equatable { 
    var value: AnyObject? 
    var title: String 
    init(title: String, value: AnyObject?) { 
     self.title = title 
     self.value = value 
    } 
    //Equatable 
    public static func ==(lhs: Item, rhs: Item) -> Bool { 
     return ((lhs.title == rhs.title) && (lhs.value === rhs.value)) 
    } 
} 

Aber ich werfe value zu gleichzusetzen will try var müssen gleichzusetzen, so dass weiche gleichzusetzen Ergebnis

if let lValue = lhs.value as? Equatable, // Error 
    let rValue = rhs.value as? Equatable { // Error 
    valueEq = (lValue == rValue) 
} else { 
    valueEq = (lhs.value === rhs.value) 
} 

Dieser Code catch Kompilierungsfehler erhalten über Generisches Gleichförmiges

Wie ich s kann ich richtig Equatable für diese Klasse tun?

UPD

ich meine Item in UITableViewCell in meinem Storyboard verwenden möchten. Ich kann nicht generisch erstellen UITableViewCell. Und wenn ich versuche Artikel als Generic<T: Equatable> Klasse, werde ich die Typen in meinen Zellen zu spezifizieren gezwungen,

var items: [Item<OnlyThisHashableClass>] 

aber ich Artikel verwenden mag, in Zellen für alle Objekte

+0

Welche Frage haben Sie mit dem Code mit euch auf dem Laufenden? – rmaddy

+1

Sie müssen einen benutzerdefinierten Werttyp erstellen, der Equatable entspricht. –

+0

Aktualisieren Sie Ihre Frage mit der genauen und vollständigen Fehlermeldung, nicht eine Zusammenfassung. – rmaddy

Antwort

1

einfache Art und Weise - Klasse bleiben nicht generische, Allgemein nur init und in GenericInit erstellen isEquals Methode

class FieldItem: CustomStringConvertible, Equatable { 
    let value: Any? 
    let title: String 
    private let equals: (Any?) -> Bool 
    init<Value: Equatable>(title: String, value: Value?) { 
     func isEquals(_ other: Any?) -> Bool { 
      if let l = value, let r = other { 
       if let r = r as? Value { 
        return l == r 
       } else { 
        return false 
       } 
      } else { 
       return true 
      } 
     } 
     self.title = title 
     self.value = value 
     self.equals = isEquals 
    } 
    //CustomStringConvertible 
    var description: String { get { return title } } 
    //Equatable 
    public static func ==(lhs: FieldItem, rhs: FieldItem) -> Bool { 
     return ((lhs.title == rhs.title) && lhs.equals(rhs.value)) 
    } 

} 
1

Sie können nicht werfen AnyObject zu ein Equatable.

Was Sie tun können, ist Item als Gattungs zu definieren, für die die value, Wrapped muss Equatable sein:

class Item<Wrapped: Equatable> { 
    var title: String 
    var value: Wrapped 

    init(title: String, value: Wrapped) { 
     self.title = title 
     self.value = value 
    } 
} 

extension Item: Equatable { 
    static func ==(lhs: Item, rhs: Item) -> Bool { 
     return lhs.title == rhs.title && lhs.value == rhs.value 
    } 
} 

Und stellen wir uns vor, dass Sie einige Klasse, Foo, dass (a) isn‘ t gleichbar; (b) ist etwas, das Sie in eine Item wickeln möchten; und (c) Sie möchten sie auf der Basis des Identity-Operators === wirklich als gleichwertig definieren. (Ich gestehe, ich finde diese Vorstellung, die du "weich gleichstellbare" ziemlich beunruhigende Vorstellung nennst, aber ich werde hier nicht darauf eingehen.)

Wie auch immer, du kannst deine Klasse Foo auf der Grundlage der Identitätsoperator:

extension Foo: Equatable { 
    static func ==(lhs: Foo, rhs: Foo) -> Bool { 
     return lhs === rhs 
    } 
} 

Oder, wenn Sie dies für viele Klassen müssen tun, könnten Sie sogar ein Protokoll für diese identitäts Gleichheit haben, und dann nicht gleichzusetzen Klassen nur, dass entsprechen könnten:

protocol IdentityEquatable: class, Equatable { } 

extension IdentityEquatable { 
    static func ==(lhs: Self, rhs: Self) -> Bool { 
     return lhs === rhs 
    } 
} 

Dann alle Klassen, die Sie wr wr ap in einem Item, die nicht Equatable diese Identität-Verhalten gleichzusetzen mit einer einzigen Code-Zeile jeder annehmen könnte:

extension Foo: IdentityEquatable { } 
extension Bar: IdentityEquatable { } 
extension Baz: IdentityEquatable { } 

Als beiseite, hat SE-0143 genehmigt und zwar nicht Teil der Sprache noch , bietet das Versprechen von Conditional Conformance in Zukunft Swift Versionen, nämlich:

class Item<Wrapped> { 
    var title: String 
    var value: Wrapped 

    init(title: String, value: Wrapped) { 
     self.title = title 
     self.value = value 
    } 
} 

extension Item: Equatable where Wrapped: Equatable { 
    static func ==(lhs: Item, rhs: Item) -> Bool { 
     return lhs.title == rhs.title && lhs.value == rhs.value 
    } 
} 

in diesem Fall würde ItemEquatable sein, wenn und nur wenn die Wrapped val Wir waren Equatable.Dies ist noch kein Teil der Sprache, aber es sieht so aus, als ob es in einer zukünftigen Version sein wird. Es ist eine elegante Lösung für dieses Problem (freilich nicht Ihre "soft equatable" Idee).

+0

aber ich benutze mein 'Item' in vielen Klassen, zum Beispiel in' UITableViewCell' in meinem Storyboard. Und wenn ich 'Item' als Generic-Klasse versuche, werde ich gezwungen, die Typen in meinen Cells anzugeben, aber ich möchte Item in Cells als Basisklasse verwenden (value - AnyObject) –

Verwandte Themen