属性声明了一个不透明的返回类型,但没有用于推断基础类型的初始化表达式

Posted

技术标签:

【中文标题】属性声明了一个不透明的返回类型,但没有用于推断基础类型的初始化表达式【英文标题】:Property declares an opaque return type, but has no initializer expression from which to infer an underlying type 【发布时间】:2021-11-02 11:55:54 【问题描述】:

我有一个协议

protocol doSomethingProtocol 
    associatedtype someType

然后我有实现这个协议的类

class doSomethingClass : doSomethingProtocol 
    typealias someType = Int


现在我想在其他类中使用这个协议作为参考

class someClass : ObservableObject 

    private var reference : doSomethingProtocol


现在我不能这样做,因为doSomethingProtocol 有一个关联类型。所以我决定使用some

class someClass : ObservableObject 

    private var reference : some doSomethingProtocol

    init()
         reference = doSomethingClass()
    


但是这不起作用。我收到错误Property declares an opaque return type, but has no initializer expression from which to infer an underlying type。为什么 ?我在类 init 中给它初始化表达式。

但是当我做这样的事情时

class someClass : ObservableObject 

    private var reference : some doSomethingProtocol = doSomethingClass()

    init()


我没有收到任何错误消息,它可以编译。为什么,两者有什么区别。

【问题讨论】:

在第一种情况下,类型未定义(即泛型),因此无法将具体分配给泛型 - 错误,在第二种情况下,类型是在初始化期间显式推断的。实际上,不清楚您要达到什么目的 - 您不能使用 doSomethingProtocol 没有关联的类型特化。 @Asperi 对不起,我没有明白你想说什么。为什么编译器不能在第一种情况下推断出来,毕竟我在初始化程序中明确地为其分配了一个对象。 【参考方案1】:

现在我不能这样做,因为 doSomethingProtocol 有一个关联类型。所以我决定使用some

这就是你出错的地方。不透明 (some) 类型解决了与具有关联类型的协议完全不同的问题。不透明类型是具体的。它是一种特定类型,在编译时已知,由函数返回。函数的调用者只是不知道它。编译器完全知道。

var reference : some DoSomethingProtocol

鉴于此信息,reference 是什么具体类型?这不知道。 init 的行为暗示了这一点,但并不知道总是如此。 (更是如此,因为这是一个可以覆盖其init 并分配其他类型的类。)

您正在尝试这样做:

private var reference : DoSomethingClass

这定义了 SomeType == DoSomethingClass,并允许 DoSomethingClass 符合 DoSomethingProtocol。

如果您试图避免确定 DoSomethingClass 在这里使用的类型,那是不可能的。要符合具有关联类型的协议,您必须提供可以在编译时确定的具体类型。

鉴于您遇到的问题,我怀疑 DoSomethingClass 的设计不正确,并且您在这里并不真正想要 PAT(具有关联类型的协议)。你可能想要一个通用的、组合的,或者可能的闭包。您可能(尽管不太可能)需要一个类型橡皮擦。但是你不想要不透明的类型。

(请大写您的类型。在 Swift 中,类型的前导小写非常令人困惑。)

【讨论】:

以上是关于属性声明了一个不透明的返回类型,但没有用于推断基础类型的初始化表达式的主要内容,如果未能解决你的问题,请参考以下文章

如何修复“函数声明了一个不透明的返回类型,但在其主体中没有返回语句来推断基础类型”错误?

如何在 SwiftUI 中使用 UIViewController 和 UIView?

SwiftUI:函数声明了一个不透明的返回类型,但其主体中的返回语句没有匹配的底层类型

如何使通用可变参数函数中先前声明的函数的返回类型成功进行上下文推断?

TypeScript类型检查机制

关于db4o的透明激活与激活声明