简体   繁体   English

通用协议Swift 4错误

[英]Generic protocol Swift 4 error

The following code use to work for me at Swift 3.2, but with the latest release of Swift 4 I am getting an strange error I can not get to understand. 以下代码在Swift 3.2上可以为我工作,但是在Swift 4的最新版本中,我遇到了一个奇怪的错误,无法理解。

I am trying to create a generic protocol like so: 我正在尝试创建一个通用协议,如下所示:

public protocol FactoryComponent {
  associatedtype Argument
  associatedtype Service
  static var factory: (Resolver) -> (Argument) -> Service { get }
}

public extension FactoryComponent {
    public typealias Factory = (Argument) -> Service
}

And using it here: 并在这里使用它:

public extension Container {
  @discardableResult
  public func register<Component: FactoryComponent>(
    factory componentType: Component.Type
  ) -> ServiceEntry<Component.Factory> { // On this line the error shows
    return self.register(componentType.Factory.self) { resolver in
      componentType.factory(resolver)
    }
  }
}

Error: 错误:

'Component' does not have a member type named 'Factory'; “组件”没有名为“工厂”的成员类型; did you mean 'Factory'? 你是说“工厂”吗?

And of course, the auto-fix does not help since the error is useless... 当然,自动修复也无济于事,因为该错误是无用的...

I checked out Swift 4 breaking changes and did not see anything involving generic protocols. 我检查了Swift 4的重大更改,没有看到涉及通用协议的任何内容。

Can somone please help me understand what does this mean? somone可以帮助我了解这是什么意思吗?

It seems that a concrete class of FactoryComponent is missing. 似乎缺少FactoryComponent的具体类。 The Factory type alias can be called only by protocol's concrete classes. 只有协议的具体类才能调用Factory类型别名。

  1. Try create an FactoryComponent concrete class that implements its protocol 尝试创建一个实现其协议的FactoryComponent具体类
  2. The Argument and Service still generic on your implementation and needs an concrete type. Argument and Service在您的实现上仍然是通用的,需要具体的类型。 My english is very bad, but I hope I've been help you. 我的英语不好,但我希望能对您有所帮助。 Check the code bellow if I'm wasn't clear on my answer. 如果回答不清楚,请检查下面的代码。

``` ```

class Resolver {}

protocol FactoryComponent {
  associatedtype Argument
  associatedtype Service
  static var factory: (Resolver) -> (Argument) -> Service { get }
}

extension FactoryComponent {
  typealias Factory = (Argument) -> Service
}

class ConcreteFactoryComponent: FactoryComponent {
  static var factory: (Resolver) -> Factory {
    return foo
  }

  static func foo(_ resolver: Resolver) -> Factory {
    let factory: Factory = { argument in return "" }
    return factory
  }

  typealias Argument = String
  typealias Service = String
}

let factory: ConcreteFactoryComponent.Factory = { argument in return "" }

``` ```

I believe the error is not really on the line with the return type. 我相信错误不是真正与返回类型有关。 The processing of generic signature resolution has changed slightly in Swift 4 due to the new default for @escaping. 由于@escaping的新默认设置,在Swift 4中,通用签名解析的处理略有变化。 The fact that the function is calling a self.register function with an identical signature as the function itself is likely the source of the issue. 该函数正在调用具有与该函数本身相同的签名的self.register函数的事实很可能是问题的根源。

From other similar instances, I would suggest looking at the signature of the Container.register. 从其他类似的实例中,我建议查看Container.register的签名。 If it happens to have an @escaping closure, then the signature of the generic function in the extension should also have one so that it is recognized as an overload. 如果碰巧有一个@escaping闭包,那么扩展中的泛型函数的签名也应该有一个,以便将其识别为重载。

See this post: https://stackoverflow.com/a/43081214/5237560 看到这个帖子: https : //stackoverflow.com/a/43081214/5237560

[EDIT] I just realized this change was between Swift 2 and 3. Leaving the answer here in case it can provide some inspiration. [编辑]我刚刚意识到此更改是在Swift 2和3之间进行的。如果可以提供一些启发,请在此处留下答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM