这就是我想要做的:
rewrite
在行/swagger/index.html?url=/swagger/v1/swagger.json
上,我遇到了一个错误protocol GenericFactory {
associatedtype Input
associatedtype Value
func create(with input: Input) -> Value
}
class Base<Factory: GenericFactory> {
var input: Factory.Input {
preconditionFailure("To be overriden")
}
}
protocol ValueProtocol {}
struct SomeInputImpl {}
protocol ValueFactory: GenericFactory where Input == SomeInputImpl, Value: ValueProtocol {}
class Child<Factory: ValueFactory>: Base<Factory> {
override var input: Factory.Input {
return SomeInputImpl()
}
}
。我不了解此错误的原因,因为swift override var input: Factory.Input {
协议中描述了输入类型,但是由于某些原因,swift会将base中的Factory.Input和Child中的Factory.input解释为不同的类型。有人可以解释一下这是怎么回事吗?
答案 0 :(得分:2)
仅是为了完成有关在Swift 5中解决此问题的要点,以下是在您的示例代码中将在Swift 5中有效的演示,但不适用于Swift 4.2。
struct Val: ValueProtocol {}
struct VF: ValueFactory {
func create(with input: SomeInputImpl) -> Val {
return Val()
}
}
let child = Child<VF>()
child.input // SomeInputImpl
但是,几乎可以肯定,使用函数而不是使用GenericFactory
会更好。使用Factory模式的主要原因是要处理缺少高阶函数和一流类型的语言,例如Java 8之前的版本。在具有高阶函数和一流类型的语言(例如Swift)中,通常不需要使用Factory模式。您可以直接直接传递函数(Input) -> Value
。
您的示例没有显示调用方,因此很难确切地知道哪种基于函数的解决方案最有效,但是在大多数情况下,泛型函数比协议+ associatedType +泛型+继承更好。特别是,将类继承混合到关联类型中会使您陷入困境(因为关联类型和类继承在某种程度上是正交的多态方法)。
答案 1 :(得分:0)
protocol ValueFactory: GenericFactory where Input: SomeInputImpl, Value: ValueProtocol {}
输入应确认SomeInputImpl。 由于SomeInputImpl是结构类型,因此无法继承。所以你必须使其成为类或协议
class SomeInputImpl {}
然后您可以覆盖输入变量
class Child<Factory: ValueFactory>: Base<Factory> {
override var input: Factory.Input {
return SomeInputImpl() as! Factory.Input
}
}