使用不透明类型和相关类型

问题描述 投票:0回答:1

假设我有一个协议Parser,定义如下:

protocol Parser {
  associatedtype Element
  associatedtype Stream
  func parse(_ stream: Stream) -> (Element, Stream)?
}

现在让我们使用以下结构来遵守此协议:

struct CharacterParser: Parser {
  let character: Character
  func parse(_ stream: String) -> (Character, String)? {
    guard stream.first == character
      else { return nil }
    return (character, String(stream.dropFirst()))
  }
}

现在,我们可以为Character编写一个整洁的扩展名以创建字符解析器:

extension Character {
  var parser: CharacterParser { return CharacterParser(character: self) }
}

let p = Character("a").parser
print(p.parse("abc"))
// Prints `Optional(("a", "bc"))`

现在,我想隐藏解析器实现的细节,并使用Swift 5.1中的新不透明类型。编译器将让我编写以下内容:

@available(OSX 10.15.0, *)
extension Character {
  var parser: some Parser { return CharacterParser(character: self) }
}

到目前为止很好。但是现在没有办法调用parse(:),因为似乎编译器不再能够解析我应该提供的参数类型。换句话说,以下内容将无法编译:

let p = Character("a").parser
print(p.parse("abc"))
// error: Cannot invoke 'parse' with an argument list of type '(String)'

我发现的唯一解决方案是定义一个继承自Parser的“更具体”协议,例如StringParser,用于在同类型约束中设置关联的类型。不幸的是,我并不特别喜欢这种方法,因为如果我定义其他方法来返回带有更详尽的类型约束的Parser实例,则无法很好地扩展。换句话说,我将以暴露特定类型(例如SomeSpecificParserType)与暴露特定协议(例如SomeSpecificParserProtocol)进行交易,而我希望保持较高的抽象级别,理想情况下仅处理some Parser返回类型。

[有没有办法提供其他信息,以指定我从属性返回的类型的关联类型仅是在属性定义上是String,以便Swift以后可以推断出p.parse的具体类型?] >

假设我有一个协议解析器,定义如下:protocol Parser {relatedtype Element relatedtype流func parse(_ stream:Stream)->(Element,Stream)? }现在,让我们...

swift swift-protocols opaque-result-type
1个回答
0
投票

Swift在使用带有关联类型的协议形式的不透明返回类型时还没有很好的支持。原因之一是,在返回此类值时,您尚无法描述协议的关联类型。因此,编译器无法推断出要用于关联类型的内容。

© www.soinside.com 2019 - 2024. All rights reserved.