我想创建一个类似以下的协议:
protocol Parser {
func parse() -> ParserOutcome<?>
}
enum ParserOutcome<Result> {
case result(Result)
case parser(Parser)
}
我希望有解析器可以返回指定类型的结果或者另一个解析器。
如果在Parser
上使用关联类型,那么就不能在enum
中使用Parser
。如果我在parse()
函数上指定一个泛型类型,那么在实现中我将无法定义它而不带有泛型类型。
我该如何实现这个需求?
使用泛型,我可以编写以下内容:
class Parser<Result> {
func parse() -> ParserOutcome<Result> { ... }
}
enum ParserOutcome<Result> {
case result(Result)
case parser(Parser<Result>)
}
这种方式下,Parser
将会以结果类型为参数。 parse()
可以返回一个 Result
类型的结果,或者任何一种输出结果为 Result
类型或者另一个以相同 Result
类型为参数的解析器的解析器。
然而,使用关联类型,就我所知,我将始终有一个 Self
约束:
protocol Parser {
associatedtype Result
func parse() -> ParserOutcome<Result, Self>
}
enum ParserOutcome<Result, P: Parser where P.Result == Result> {
case result(Result)
case parser(P)
}
在这种情况下,我无法使用任何会返回相同Result
类型的解析器,它必须是相同类型的解析器。
我希望通过Parser
协议获得与通用定义相同的行为,并且我想在类型系统范围内做到这一点,而不引入新的装箱类型,就像我使用普通泛型定义一样。
对我来说,似乎在Parser
协议中定义associatedtype OutcomeParser: Parser
,然后返回由该类型参数化的enum
可以解决问题,但如果我尝试以那种方式定义OutcomeParser
,就会出现错误:
Type may not reference itself as a requirement
AnySequence
使用了类型擦除,它在标准库中,并且被苹果明确地文档化为“类型擦除”。到目前为止,它仍然感觉像是一种hack,但我正在深入研究它。 - rid