当前位置: 首页 > 知识库问答 >
问题:

为什么swift编译器在使用/不使用Equable协议的等号操作符时表现不同

况鸿雪
2023-03-14

我在Swift 4.0的操场上有一个非常简单的类,它重写了==运算符

我不明白为什么当类继承/不继承等价协议时,Swift编译器的行为不一样。

这里是继承Equatable协议时的类

class Test: Equatable  {
    var value = 0

    init(_ initialValue:Int) {
        value = initialValue
    }

    static func == (lhs:Test, rhs:Test) -> Bool {
        return lhs.value == rhs.value ? true : false
    }
}

let test1 = Test(0)
var test4:Test? = nil

if test1 == test4 {
    print("test1 and test4 are equals")
} else {
    print("test1 not equals to test4")
}

当该代码执行时,它显示“test1不等于test4”。这是预期的行为。

接下来,当我将“等价”协议从类中移除时

class Test  {
    var value = 0

    init(_ initialValue:Int) {
        value = initialValue
    }

    static func == (lhs:Test, rhs:Test) -> Bool {
        return lhs.value == rhs.value ? true : false
    }
}

let test1 = Test(0)
let test3 = Test(0)

var test4:Test? = nil


if test1 == test4 {
    print("test1 and test4 are equals")
} else {
    print("test1 not equals to test4")
}

我在行上收到编译错误

if test1 == test4 {

并显示以下消息:“可选类型'Test?'的值未展开;您的意思是使用“!”还是“?”?

为什么等同/不等同的行为是不同的?

事实上,当类继承自Equable时,我也期望出现相同的编译错误,因为我将非可选与可选进行了比较。

当一个类继承Equable时,比较非可选和可选是否安全?

共有2个答案

陈博容
2023-03-14

如果你命令点击符合Equalable的那个,它会把你带到这里:

/// ....
/// You can also use this OPERATOR TO COMPARE A NON-OPTIONAL VALUE TO AN
/// OPTIONAL that wraps the same type. The non-optional value is wrapped as an
/// optional before the comparison is made. In the following example, the
/// `numberToMatch` constant is wrapped as an optional before comparing to the
/// optional `numberFromString`:
///
///     let numberToFind: Int = 23
///     let numberFromString: Int? = Int("23")      // Optional(23)
///     if numberToFind == numberFromString {
///         print("It's a match!")
///     }
///     // Prints "It's a match!"
///
/// ....
public func ==<T>(lhs: T?, rhs: T?) -> Bool where T : Equatable

但是对于不符合Equatable的版本,你不会得到这个。它将只使用您提供的静态函数。

章锦
2023-03-14

有一个< code>==运算符

public func ==<T>(lhs: T?, rhs: T?) -> Bool where T : Equatable

如果基础类型是Equable,则允许比较两个可选值。在您的第一种情况下调用该运算符

let test1 = Test(0)
var test4:Test? = nil

if test1 == test4 { ... }

(左操作数自动包装为可选值。)

如果< code>Test不符合< code>Equatable,则运算符不匹配,因此没有< code>==运算符进行两次< code >测试?操作数。因此编译器出错。

 类似资料:
  • 我对Swift中关于var和关键字{get set}的使用的协议有疑问。 来自Apple文档: 这将不是公正的: 我错过了什么?

  • 问题内容: 我正在尝试通过符合协议的编码模型来获取数据。但是它无法像下面的代码那样调用func : 但是在另一个演示中,效果很好,为什么呢? 问题答案: 解决方案1。 https://github.com/satishVekariya/SVCodable 试试这个代码,它扩展了可编码 解决方案2。 避免污染带有扩展名的Apple提供的协议 用

  • 我们知道,JVM同时使用解释器和JIT编译器。JIT编译器将重复的字节码转换为机器码并存储在内存中。现在,当解释器逐行翻译字节码并运行它时,它将跳过已转换并存储在内存中的重复代码的翻译部分,但将直接运行它。从而减少了并发冗余翻译。 那么为什么Java在JVM中使用解释器呢?像JIT这样的编译器可以一次性完成将字节码转换为机器码的整个任务吗?

  • 问题内容: 当我看到Python的编译器软件包的文档时,我感到很惊讶,但是注意到它已经在Python 3.0中消失了,没有任何明确的替换或解释。 我似乎在python-dev上找不到有关如何做出此决定的任何讨论-有人对此决定有任何见识吗? 问题答案: 我相信该功能现已内置: 编译 AST

  • 问题内容: 我对一方面用于协议的关联类型的语法和另一方面用于泛型类型的语法之间的区别感到困惑。 例如,在Swift中,可以使用以下方式定义通用类型 而使用诸如 为什么后者不只是: 是否有某种深层的原因(或者也许是显而易见的,对我来说就迷失了),原因是该语言未采用后一种语法? 问题答案: 在开发人员列表中已对此进行了多次讨论。基本答案是关联类型比类型参数更灵活。虽然您在这里有一个类型参数的特定情况,

  • 问题内容: 我试图在我快速编写的类上使用NSCoding协议,但是似乎无法弄清楚为什么当我实现所需的方法时,编译器会抱怨它“不符合协议NSCoding”: 这是一个错误还是我只是缺少一些东西? 问题答案: 如您在报告导航器中详细的编译器消息中所见,您的方法未正确声明: (在beta版本之间可能有所变化。)此外,该方法必须标记为: 在 Swift 3中 ,所需的方法是