为什么使用 Self 作为返回类型不被视为协议的约束?

问题描述

这是一个有效的 Swift 协议声明:

protocol Proto1: class {
    func method1() -> Self
    func method2() -> [Proto1]
}

但这不是:

protocol Proto2: class {
    func method1(param: Self)
    func method2() -> [Proto2]
}

错误信息是:

Protocol 'Proto2' 只能用作通用约束,因为它 有自己或相关的类型要求

所以看起来,当使用 Self 作为函数的返回类型时,Swift 并不认为这是被定义的协议的约束,因此可以使用协议本身作为函数的返回类型。但是当使用 Self 作为函数的参数类型时,行为完全不同。

我想知道为什么会有这样的差异?

解决方法

因为将 Self 作为方法的参数类型没有用。假设你可以做到:

protocol P {
    func f(_ x: Self)
}

class A: P {
    func f(_ x: Self) {
        // not relevant
    }
}

class B: A { }

现在假设我有:

func g(x: A) {
    // what can I do with x?
}

事实是,没有办法调用 x.f。因为我可以将 B 的实例传递给 x,在这种情况下 x.f 将接受 Bx 可能是 A 的任何子类的实例,我在编译时无法知道,所以我不知道可以传递给 x.f 什么。


将其与用作返回类型的 Self 进行比较:

protocol P {
    func f() -> Self
}

// Implementation:
class A: P {
    func f() -> Self {
        self
    }
}

class B: A { }

func g(x: A) {
    let foo: A = x.f()
}

在这里,我们知道我可以至少x.f 的返回值分配给 A 类型的变量。即使 xB 的实例,这意味着 f 返回 B,我们仍然可以将其分配给 A 类型的变量。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...