无法比较不透明类型的两个实例

Unable to compare two instances of opaque types

有趣的是,我们现在可以声明 return 具有关联类型的协议的值。

下面报错,我没看懂错误

protocol Plant: Equatable {
    var maintenance: String { get }
}

struct Rose: Plant {
    let height: Float // inches
    let maintenance = "Water once a day."
}

struct Orchid: Plant {
    let height: Float // inches
    let maintenance = "Water once a month."
}

func makePlant1() -> some Plant {
    Rose(height: 4)
}

func makePlant2() -> some Plant {
    Orchid(height: 8)
}

let plant1: some Plant = makePlant1()
let plant2: some Plant = makePlant2()

func asdf() {
    let condition: Bool = (plant1 == plant2) // error: ambiguous without more context
    print(condition)
}

当您向 return some Plant 声明一个函数时,编译器将查看函数的内容以查看 returned 的真实类型,在您的示例中returning 不同的类型,RoseOrchid

这打破了 Equatable 的要求,即 Self 必须相同,您使用 some 并不意味着此要求消失。

您收到的错误消息有点令人困惑,但如果您将其更改为

print(plant1 == plant2)

错误信息更丰富

Cannot convert value of type 'some Plant' (result of 'makePlant2()') to expected argument type 'some Plant' (result of 'makePlant1')

为了能够在此处使用==,您需要使用由相同函数创建的对象

func makePlant1(_ value: Float) -> some Plant {
    Rose(height: value)
}

let plant1 = makePlant1(4)
let plant2 = makePlant1(4)
let plant3 = makePlant1(6)

print(plant1 == plant2) // true
print(plant1 == plant3) // false

Here 是一篇关于 hackingwithswift.com

主题的内容丰富的文章

协议 Plant 符合 Equatable。这意味着符合 Plant 的类型也符合 Equatable.

Rose符合Plant,所以也是Equatable:可以区分两个Rose

Orchid 相同:您可以区分两个 Orchids。

但是你不能将 Rose 等同于 Orchid:它们都遵循相同的协议,但它们不继承自相同的 class。

如果您尝试将相同类型的两个等同起来,它会起作用 - 请参阅下面的示例。

1) 等同于遵循相同协议的实例

protocol Plant: Equatable {
    var maintenance: String { get }
}

struct Rose: Plant {
    let height: Float // inches
    let maintenance = "Water once a day."
}

struct Orchid: Plant {
    let height: Float // inches
    let maintenance = "Water once a month."
}

    func makePlant2() -> some Plant {
        Orchid(height: 8)
    }

    func makePlant3() -> some Plant {
        Orchid(height: 10)
    }

    func compare() {
        let plant2: Orchid = makePlant2() as! Orchid
        let plant3: Orchid = makePlant3() as! Orchid

        let conditionPlant: Bool = (plant3 == plant2) // both are Equatable of the same type
        print(conditionPlant)
    }

2) 等同于从同一类型继承的 classes

protocol Plant: Equatable {
    var maintenance: String { get }
}

class Tree: Plant {
    static func == (lhs: Tree, rhs: Tree) -> Bool {
        lhs.name == rhs.name
    }
    
    let name: String
    var maintenance = "Never"
    
    init(name: String) {
        self.name = name
    }
}

class Oak: Tree { }
class Sequoia: Tree { }

    func makeTree1() -> Tree {
        Oak(name: "Shady oasis")
    }
    
    func makeTree2() -> Tree {
        Sequoia(name: "Old woody")
    }

    func compare() {
        let tree1 = makeTree1()
        let tree2 = makeTree2()

        let conditionTree: Bool = (tree1 == tree2) // both are Equatable, inherit from the same type
        print(conditionTree)
    }