属性声明了一个不透明的返回类型,但没有用于推断基础类型的初始化表达式
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:函数声明了一个不透明的返回类型,但其主体中的返回语句没有匹配的底层类型