2016-04-20 4 views
0

** REWRITE **Hash-Probleme mit einer Wrapper-Klasse um NSUUID als Schlüssel

OK, es stellt sich heraus, dass ich wirklich eine andere Frage stelle. Ich verstehe über HashValue und ==, also ist das nicht relevant.

Ich möchte meine Wrapper-Klasse BUUID "das Richtige tun" und so handeln wie NSUUID in einem Dictionary.

Siehe unten, wo sie nicht.

import Foundation 
class BUUID: NSObject { 
    init?(str: String) { 
     if let uuid = NSUUID(UUIDString: str) { 
      _realUUID = uuid 
     } 
     else { 
      return nil 
     } 
    } 

    override init() { 
     _realUUID = NSUUID() 
    } 

    private var _realUUID: NSUUID 

    override var description: String { get { return _realUUID.UUIDString } } 
    override var hashValue: Int { get { return _realUUID.hashValue } } 
    var UUIDString: String { get { print("WARNING Use description or .str instead"); return _realUUID.UUIDString } } 
    var str: String { get { return _realUUID.UUIDString } } 
} 
func ==(lhs: BUUID, rhs: BUUID) -> Bool { return lhs._realUUID == rhs._realUUID } 

let a = BUUID() 
let b = BUUID(str: a.str)! 
print("a: \(a)\nb: \(b)") 
print("a === b: \(a === b)") 
print("a == b: \(a == b)") 

var d = [a: "Hi"] 
print("\(d[a]) \(d[b])") 


let nA = NSUUID() 
let nB = NSUUID(UUIDString: nA.UUIDString)! 
print("na: \(nA)\nnB: \(nB)") 
print("nA === nB: \(nA === nB)") 
print("nA == nB: \(nA == nB)") 

var nD = [nA: "Hi"] 
print("\(nD[nA]) \(nD[nB])") 

Ergebnisse. Beachten Sie, dass ich mit NSUUID nB nachschlagen und zurückbekommen kann, was ich unter nA gestellt habe. Nicht so mit meinem BUUID.

a: 9DE6FE91-D4B5-4A6B-B912-5AAF34DB41C8 
b: 9DE6FE91-D4B5-4A6B-B912-5AAF34DB41C8 
a === b: false 
a == b: true 
Optional("Hi") nil 

nA: <__NSConcreteUUID 0x7fa193c39500> BB9F9851-93CF-4263-B98A-5015810E4286 
nB: <__NSConcreteUUID 0x7fa193c37dd0> BB9F9851-93CF-4263-B98A-5015810E4286 
nA === nB: false 
nA == nB: true 
Optional("Hi") Optional("Hi") 
+0

Der Hash-Wert nicht eindeutig sein muss. Die einzige Voraussetzung ist, dass verschiedene Elemente unterschiedliche Hashes haben. –

+0

Verschiedene Schlüssel können identische Hashes haben, aber die Gleichheitsoperation sollte für diese Schlüssel false zurückgeben. Ich habe fast ein illustrierendes Beispiel vorbereitet. Lass es mich posten. –

+1

Das ist definitiv nicht gut, alle Schlüssel mit dem gleichen Hash zu haben. In diesem Fall erhalten wir den schlimmsten Fall, wenn die Suchelementkomplexität auf O (n) fällt (erschöpfende Suche). Aber es wird funktionieren. –

Antwort

2

von NSObject Vererben geht auch davon aus isEqual: -> Bool Überlastung Methode (Objekt ANYOBJECT?):

import Foundation 
class BUUID: NSObject { 
    init?(str: String) { 
     if let uuid = NSUUID(UUIDString: str) { 
      _realUUID = uuid 
     } 
     else { 
      return nil 
     } 
    } 

    override init() { 
     _realUUID = NSUUID() 
    } 

    private var _realUUID: NSUUID 

    override func isEqual(object: AnyObject?) -> Bool { 
     guard let buuid = object as? BUUID else { 
      return false 
     } 

     return buuid._realUUID == _realUUID 
    } 
    override var description: String { get { return _realUUID.UUIDString } } 
    override var hashValue: Int { get { return _realUUID.hashValue } } 
    var UUIDString: String { get { print("WARNING Use description or .str instead"); return _realUUID.UUIDString } } 
    var str: String { get { return _realUUID.UUIDString } } 
} 
func ==(lhs: BUUID, rhs: BUUID) -> Bool { return lhs._realUUID == rhs._realUUID } 

let a = BUUID() 
let b = BUUID(str: a.str)! 
print("a: \(a)\nb: \(b)") 
print("a === b: \(a === b)") 
print("a == b: \(a == b)") 

var d = [a: "Hi"] 
print("\(d[a]) \(d[b])") 


let nA = NSUUID() 
let nB = NSUUID(UUIDString: nA.UUIDString)! 
print("na: \(nA)\nnB: \(nB)") 
print("nA === nB: \(nA === nB)") 
print("nA == nB: \(nA == nB)") 

var nD = [nA: "Hi"] 
print("\(nD[nA]) \(nD[nB])") 
+1

Vielen Dank für Ihre Hilfe zu diesem Problem. Objective-C kann ein schweres Erbe sein, wenn man Swift als Neuanfang betrachtet. – BaseZen

0

Diese Antwort ist relevant zunächst Fragen gestellt: Warum das möglich ist zwei mit Hashes der identischen Schlüssel Schlüssel-Wert-Paare zu bekommen in einem Wörterbuch

Dieses Beispiel zeigt, dass die Schlüssel im Wörterbuch identisch Hashes haben

func ==(lhs: FooKey, rhs: FooKey) -> Bool { 

    return unsafeAddressOf(lhs) == unsafeAddressOf(rhs) 
} 

class FooKey: Hashable, Equatable { 

    var hashValue: Int { 

     get { 
      return 123 
     } 
    } 
} 

var d = Dictionary<FooKey, String>() 

let key1 = FooKey() 
let key2 = FooKey() 

d[key1] = "value1" 
d[key2] = "value2" 

Ausgang

:, aber Gleichheit Betrieb sollte für verschiedene Schlüssel false zurück 210
[FooKey: "value1", FooKey: "value2"] 

Das ist definitiv nicht gut, alle Schlüssel mit dem gleichen Hash zu haben. In diesem Fall erhalten wir den schlimmsten Fall, wenn die Suchelementkomplexität auf O (n) fällt (erschöpfende Suche). Aber es wird funktionieren.

1

So ist die Antwort auf nicht BUUID von NSObject erben machen, die die Swiftiness vorran == Hinterschneidungen. So

:

extension BUUID: Hashable {} 
class BUUID: CustomStringConvertible { 
    // take away all 'override' keywords, nothing to override 
    // otherwise same as above 
} 

Interessant!

+0

Wenn Sie von NSObject erben, müssen Sie Folgendes überladen: func isEqual (Objekt: AnyObject?) -> Bool –

Verwandte Themen