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

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

齐望
2023-03-14

这是SWIFT中的有效协议声明:

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

但这不是:

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

错误消息为:

协议“proto2”只能用作泛型约束,因为它具有自身或关联的类型要求

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

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

共有1个答案

鱼阳伯
2023-03-14

因为将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类型的变量。

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

  • 问题内容: 从Java 5开始,我们被允许具有协变返回类型。Java API为什么不利用此优势? 举个例子。为什么不重写以返回对象?在我看来,它将在所有情况下都向后兼容。 问题答案: 通常,这确实是为了保持向后兼容性。请注意,兼容性也必须保持在字节码级别,并且更改返回类型也会更改字节码。因此,通常来说,如果有任何子类可能覆盖了所讨论的方法,那么切换到协变返回类型将破坏这些类。 由于是抽象的,因此显

  • 我听到一些人说,即使在使用获得种子之后,使用也是很糟糕的。为什么会这样?我想知道事情是怎么发生的...抱歉,我又问了一个问题..但是,有什么办法可以替代这一点呢?

  • 可能重复: 是否可能将可空类型作为泛型参数? 我遇到了一个关于泛型类型约束的非常奇怪的事情。我有一门课是这样的: 但是,我发现我不能像预期的那样使用null类型: 我得到一个错误,必须是引用类型。Nullable真的只是一个语法糖的结构,使其看起来像引用类型吗?

  • 问题内容: 我问了一个一般性的Spring问题:自动播发Spring Bean,并让多个人回答说应尽可能避免调用Spring 。这是为什么? 我还应该如何访问配置了Spring创建的Bean? 我在非Web应用程序中使用Spring,并计划按照LiorH的描述访问共享对象。 修正案 我接受下面的答案,但这是Martin Fowler的另一种选择,他讨论了依赖注入与使用(本质上与调用相同)的优点。

  • 问题内容: 当使用Eclipse从表中生成JPA实体时(对于Java EE Developers,它是Juno 4.2),它建议作为我设置为的属性的默认映射类型。 这很烦人,因为我必须将它们全部手动设置。 有人遇到过这种问题并且知道该怎么办吗?这是错误吗?Eclipse Indigo的行为并非如此。 这是来自:(但根据此文件应映射到此文件,必须是错误的文件- 但是如何找出正确的文件?) 我的SQL