美文网首页Swift
Swift Hashable

Swift Hashable

作者: Nomo_C | 来源:发表于2020-04-18 13:26 被阅读0次

以下是对官方文档的一些总结,如有错误请指出

在swift中想要作为dictionary或者set的key,必须遵守Hashable 协议。

You can use any type that conforms to the Hashable protocol in a set or as a dictionary key

标准库重的很多属性都遵守Hashable。其他一些属性比如 optionals、 arrays 、 ranges,如果他们包装的类型遵守Hashable ,它们也将自动遵守Hashable

Many types in the standard library conform to Hashable: Strings, integers, floating-point and Boolean values, and even sets are hashable by default. Some other types, such as optionals, arrays and ranges automatically become hashable when their type arguments implement the same

对于自定义类型也可以遵守Hashable 协议。
需要实现hash(into:)方法,通常情况下也需要一起实现 Equatable协议

注意如果 a == b,则a.hashValue == b.hashValue 一定成立

枚举

1.对于自定义的没有关联值的枚举类型,它会自动遵守Hashable 协议,甚至不需要申明
2.对于自定义有关联类型的枚举类型。如果关联类型遵守Hashable 协议,编译器会自动提供Hashable的实现,只需要声明。当然也可以自己手动实现。
3.如果关联类型不遵守Hashable 协议,则需要手动遵守Hashable 协议

enum CustomType {
    case a
    case b
    
}

// 编译器自动实现
enum CustomType2: Hashable {
    case a(String)
    case b(Int)
}

// 自定义实现
enum CustomType3: Hashable {
    case a(String)
    case b(Int)
    
    static func ==(lhs: CustomType3, rhs: CustomType3) -> Bool {
        switch (lhs, rhs) {
        case (.a(let lhsValue), .a(let rhsValue)):
            return lhsValue == rhsValue
        case (.b(let lhsValue), .b(let rhsValue)):
            return lhsValue == rhsValue
        default:
            return false
        }
    }
    
    func hash(into hasher: inout Hasher){
        switch self {
        case .a(let value):
             hasher.combine(value)
        case .b(let value):
            hasher.combine(value)
        }
       
    }
}

测试代码

func testHashale1() {
        let a = CustomType.a
        let a2 = CustomType.a
        let b = CustomType.b
        XCTAssertTrue(a == a2)
        XCTAssertTrue(a != b)
        XCTAssertTrue(a.hashValue != b.hashValue)
        XCTAssertTrue(a.hashValue == a2.hashValue)
        
        let dict = [a:"123"]
        print("\(a2.hashValue) \(a.hashValue) \(dict[a2] as Any)")
        XCTAssertTrue(dict[a2]! == "123")
    }
    
    func testHashale2() {
        let a = CustomType2.a("a")
        let a2 = CustomType2.a("a")
        let a3 = CustomType2.a("b")
        let b = CustomType2.b(1)
        let b1 = CustomType2.b(1)
        let b2 = CustomType2.b(2)
        XCTAssertTrue(a == a2)
        XCTAssertTrue(a != a3)
        XCTAssertTrue(a != b1)
        XCTAssertTrue(b == b1)
        XCTAssertTrue(b2 != b1)
        XCTAssertTrue(a.hashValue != b.hashValue)
        XCTAssertTrue(a.hashValue == a2.hashValue)
        
        let dict = [a:"123"]
        print("\(a2.hashValue) \(a.hashValue) \(dict[a2] as Any)")
        XCTAssertTrue(dict[a2]! == "123")
    }

结构体

1.对于结构体存储的属性,如果都是可哈希的,只需要声明编译器会自动遵守Hashable 协议,当然也可以自己手动实现
2.对于结构体存储的属性,如果不都是可哈希的,则需要手动遵守Hashable 协议。

struct Pet:Hashable {
  var name:String
}

struct Student: Hashable {
  var age:Int
  var name:String
//  var pet:Pet
}

测试代码

 func testHashale3() {        
        let a = Student(age:10, name:"a")
        let a2 = Student(age:10, name:"a")
        let b = Student(age:10, name:"b")
        XCTAssertTrue(a == a2)
        XCTAssertTrue(a != b)
        XCTAssertTrue(a.hashValue != b.hashValue)
        XCTAssertTrue(a.hashValue == a2.hashValue)
        
        let dict = [a:"123"]
        print("\(a2.hashValue) \(a.hashValue) \(dict[a2] as Any)")
        XCTAssertTrue(dict[a2]! == "123")
    }

须要手动遵守Hashable 协议

class Person: Hashable {
    var age:Int
    var name:String
    init(age:Int, name:String) {
        self.age = age
        self.name = name
    }
    
    static func == (lhs: Person, rhs: Person) -> Bool {
        lhs.age == rhs.age && lhs.name == rhs.name
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(age)
        hasher.combine(name)
    }
}

测试代码

func testHashale4() {
       let a = Person(age:10, name:"a")
       let a2 = Person(age:10, name:"a")
       let b = Person(age:10, name:"b")
       XCTAssertTrue(a == a2)
       XCTAssertTrue(a != b)
       XCTAssertTrue(a.hashValue != b.hashValue)
       XCTAssertTrue(a.hashValue == a2.hashValue)
       
       let dict = [a:"123"]
       print("\(a2.hashValue) \(a.hashValue) \(dict[a2] as Any)")
       XCTAssertTrue(dict[a2]! == "123")   
   }

相关文章

网友评论

    本文标题:Swift Hashable

    本文链接:https://www.haomeiwen.com/subject/dgpvvhtx.html