Swift5.0 ==与===的区别

首先看一段代码:

import XCTest

class Hero {
    var killedEnemy:[Enemy] = []
    
    func kill(ennmy: Enemy) {
        killedEnemy.append(ennmy)
    }
}

class Enemy {
    
}

protocol InstanceEquatable: class, Equatable {}

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

extension Enemy: InstanceEquatable {}


class Tests: XCTestCase {

    override func setUp() {
    }

    override func tearDown() {
    }

    func testDestoryingPerson() {
        let hero = Hero()
        let enemy1 = Enemy()
        let enemy2 = Enemy()
        let enemy3 = Enemy()
        hero.kill(ennmy: enemy1)
        XCTAssertTrue(hero.killedEnemy.contains(enemy2))
    }

}

这段代码在说什么

在代码中,我们看到 Enemy 通过 InstanceEquatable 拓展遵循了 Equatable 协议并重载了 == 运算符。
声明了只有内存地址相等的状态下才符合 == 的定义。
此时 == 与 === 的含义相同。

在这个前提下,调用 contains 函数的含义就变成了判断 hero 干掉的 ememy 中,是否包含目标对象引用的内存地址,而不是与目标对象内容相同的实例。

=== 和 == 的区别

简单来说,Swift 中提供了两种用于判等的操作符,一个是 == ,一个是 ===

== 通常是用于判定两个对象的内容是否相同 === 通常是用于判定两个对象引用的是否为同一块内存地址。

深入一下

对于类类型来说,会存在多个实例指向同一个内存地址的情况,这是由于类类型本身是引用类型的缘故,类引用保存在 RTS (Run Time Stack) 上,而它们的实例保存在内存的堆上。

当我们使用 == 时,我们只是想验证两个实例是否相同,而不是验证两个实例是同一个实例(地址是否相同)。
此时我们就需要提供一个验证两个实例相同的规则。

通常状态下,自定义类和结构体是没有默认的 == 和 != 行为,我们需要让这些类型遵守 Equatable 协议并重载 static func == (lhs:, rhs:) -> Bool 函数,举个例子,我们给敌人加上名字和ID,像这样:

class Enemy: Equatable {
    var id: Int = 0
    var name = ""
    
    init(id: Int, name: String) {
        self.id=id
        self.name = name
    }
	//不同的ID可以有相同的名字,所以我们判断是否是同一个敌人应该用ID去判断,对吧?
	static func == (lhs: Enemy, rhs: Enemy) -> Bool {
        return lhs.id == rhs.id
    }
}
//我们多创建几个敌人
let e1 = Enemy(id: 1, name: "B")
let e2 = Enemy(id: 1, name: "B")

let e3 = e1

//来比较一下吧,是否是同一个敌人:
func compare() {
    if e1 == e2 {
        print("the two Enemy are equal!")
        //很明显,虽然e1和e2是两个对象,但是由于他们的ID相同,所以我们认为他们是同一个敌人
    } 
    
    if e1 === e2 {
        
    } else {
    	//而===是检查的是引用的内存地址是否相同。由于 person1 和 person2 是完全 2 个独立构造的实例,所以它们在堆上的地址,也就是内存地址是不一样的,所以会走这里
        print("the two Enemy are not identical!")
    }
    
	if e1 === e3 {
		//正如我们所说的那样,类类型是引用类型,上面这段代码将 e1 的引用赋值给了 e3,现在它们同时指向 e1 指向的内存地址。所以会走这里
        print("the two Enemy are identical!")
    } else {

    }
}

发布了249 篇原创文章 · 获赞 926 · 访问量 149万+

猜你喜欢

转载自blog.csdn.net/youshaoduo/article/details/102936592
今日推荐