Swift自定义Class实现Hashable

假如有个Bit类,其中含有CGPoint类型的point属性,Class定义如下

class Bit {
    var point : CGPoint
    init(point : CGPoint) {
        self.point = point
    }
}

疑问:Bit之间怎么实现比较? 答案:实现Hashable协议就可以,而Hashable实际上又需要实现Equatable协议

1.实现Hashable

当给类增加Hashable协议后,XCode编译抛出"Type ‘Bit‘ does not conform to protocol ‘Hashable‘.Command+click点击Hashable的定义会发现如下代码:

  protocol Hashable : Equatable {
    /// Returns the hash value.  The hash value is not guaranteed to be stable
    /// across different invocations of the same program.  Do not persist the hash
    /// value across program runs.
    var hashValue: Int { get }
}

我们需要实现hashValue属性的getter,总所周知String类型是实现了Hashable的(String类型之间是可以直接比较,排序),所以可以利用String这点来实现Getter,如下代码:

var hashValue : Int {
    get {
        return "\(self.point.x),\(self.point.y)".hashValue
    }
}

增加代码后,发现编译器依然报错"Type ‘Bit‘ does not conform to protocol ‘Equatable‘"-没有实现Equatable协议。

2.实现Equatable

Commend+click点击Hashable定义,进入后再点击Equatable协议定义,可以看到如下定义:

protocol Equatable {
    func ==(lhs: Self, rhs: Self) -> Bool
}

我们会发现Equatable协议是需要实现一个函数,即==函数,那么我们究竟怎么来实现呢?

首先,我们利用getter返回值hashable来进行比较来实现,函数实现代码如下:

func ==(lhs: Bit, rhs: Bit) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

以上实际上是实现重载运算符==在下面代码中,我们发现2个point之间可以直接进行比较了。

最终代码如下

// Playground - how to implement Hashable and Equatable

import UIKit

//MARK: - Equatable
func ==(lhs: Bit, rhs: Bit) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

class Bit : Hashable {

    var point : CGPoint

    //MARK: - Hashable
    var hashValue : Int {
        get {
            return "\(self.point.x),\(self.point.y)".hashValue
        }
    }

    //MARK: - Bit
    init(point: CGPoint) {
        self.point = point
    }

}

var point_a_1_0 = Bit(point: CGPoint(x: 1, y: 0))
var point_b_1_0 = Bit(point: CGPoint(x: 1, y: 0))
var point_c_0_1 = Bit(point: CGPoint(x: 0, y: 1))

point_a_1_0 == point_b_1_0
point_a_1_0 == point_c_0_1

以上代码在XCode6 GM测试通过。

原文:http://www.swiftcoder.info/dev/codefellows/2014/8/2/how-to-implement-hashable-for-your-custom-class

时间: 2024-10-17 05:33:42

Swift自定义Class实现Hashable的相关文章

[IOS]swift自定义uicollectionviewcell

刚刚接触swift以及ios,不是很理解有的逻辑,导致某些问题.这里分享一下swift自定义uicollectionviewcell 首先我的viewcontroller不是直接继承uicollectionviewcontroller,而是添加的uicollectionview到我的storyboard, 然后再新建一个swift的文件,让这个swift继承uicollectionviewcell import Foundation class SVGCell :UICollectionView

swift 自定义TabBarItem

1.效果图     2.NewsViewController.swift // // NewsViewController.swift // NavigationDemo // // Created by 赵超 on 14-6-27. // Copyright (c) 2014年 赵超. All rights reserved. // import UIKit class NewsViewController: UIViewController { override func viewDidLo

swift 自定义弹框

// //  ViewController.swift //  animationAlert // //  Created by su on 15/12/9. //  Copyright © 2015年 tian. All rights reserved. // import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //灰色的遮挡板 let o

Swift:自定义Response

//调用的方法 func refresh(){ //如果有上拉加载更多 正在执行,则取消它 if self.tableView.mj_footer.isRefreshing() { self.tableView.mj_footer.endRefreshing() } //根据 tab name 获取帖子列表 TopicListModel.getTopicList(tab){ //自定义的Response (response:V2ValueResponse<[TopicListModel]>)

Swift - 自定义单元格实现微信聊天界面

1,下面是一个放微信聊天界面的消息展示列表,实现的功能有: (1)消息可以是文本消息也可以是图片消息 (2)消息背景为气泡状图片,同时消息气泡可根据内容自适应大小 (3)每条消息旁边有头像,在左边表示发送方,在右边表示接收方 2,实现思路 (1)需要定义一个数据结构保存消息内容 MessageItem (2)继承UITableViewCell实现自定义单元格,这里面放入头像和消息体 (3)继承UITableView实现自定义表格,通过读取数据源,进行页面的渲染 (4)消息体根据内容类型不同,用不

Swift 自定义Subscript

Swift可以方便给自定义类加下标,其中参数和返回值可以在类里定义为任意类型: subscript(parameters) -> ReturnType { get { //return someValue } set (newValue) { //setSomeValue() } }/* 何问起 hovertree.com */ 下标通常是访问某些方法的快捷方式,就算对NSArray操作的时候一样. 和计算属性一样,下标也能以只读或只写的方式出现,如只读下标: subscript(paramet

swift自定义转场动画(比较有难度)

一 转场效果图和采用转场方式 1 转场效果图 : 2 采用方式 (方法): --> 2.1 自定义转场动画 --> 2.2 协议 二 转场实现需要获取的东西 1 获取转场前图片的frame 2 设置一张临时imageView作为转场图片(图片并不是真实存在的) 3 获取图片放大展示的frame 三 转场图解 四 转场动画思想 1 通过在实现转场动画的类中定义协议方法,定义代理属性,明确谁可以提供需要的frame和imageView,将对方设置为代理,让代理提供需求,达到转场目的. 2 明确代码

Swift 自定义UIView的点击穿透

早上写自定义View的时候,发现一个神奇的问题,因为真的比较神奇,所以就记录下 一般我们自定义View的时候喜欢这样写: override init(frame: CGRect) { super.init(frame:frame) //添加其他views self.addSubview(view1) } 这样的方式,创建出的View是不会有穿透点击效果的 然而,有一个绘制图形的接口是: override func drawRect(rect: CGRect) { //添加其他Views self

Swift 自定义打印方法

#代码如下 // MARK:- 自定义打印方法 func MLLog<T>(_ message : T, file : String = #file, funcName : String = #function, lineNum : Int = #line) { #if DEBUG // 创建一个日期格式器 let dformatter = DateFormatter() // 为日期格式器设置格式字符串 dformatter.dateFormat = "yyyy-MM-dd HH: