返回符合一般约束的对象

时间:2019-04-30 10:34:36

标签: swift generics swift-protocols

我正在尝试为我的Builder创建一个ComplexObject

import Foundation

class ComplexObject {
    // lots of stuff

    init<ObjectType, T>(_ closure: ((ObjectType) -> T)) {
        // lots of init/setup code
    }

    // other initializers with generics, constructed 
    // by other Builders than ConcreteBuilder<O> below
}

protocol BuilderType {
    associatedtype ObjectType
    func title(_: String) -> Self
    func build<T>(_ closure: ((ObjectType) -> T)) -> ComplexObject
}

struct Injected<O> {
    //...
}

extension ComplexObject {
    static func newBuilder<Builder: BuilderType, O>(someDependency: Injected<O>) -> Builder where Builder.ObjectType == O {
        // vvvv
        return ConcreteBuilder(someDependency: someDependency)
        // ^^^^
        // Cannot convert return expression of type 'ComplexObject.ConcreteBuilder<O>' to return type 'Builder'
    }

    struct ConcreteBuilder<O>: BuilderType {
        private let dependency: Injected<O>

        private var title: String

        init(someDependency: Injected<O>) {
            self.dependency = someDependency
        }

        func title(_ title: String) -> ConcreteBuilder<O> {
            var builder = self
            builder.title = title
            return builder
        }

        func build<T>(_ closure: ((O) -> T)) -> ComplexObject {
            return ComplexObject(closure)
        }
    }
}

但是swiftc抱怨return ConcreteBuilder(...)这一行

Cannot convert return expression of type 'ComplexObject.ConcreteBuilder<O>' to return type 'Builder'

我也尝试过

static func newBuilder<Builder: BuilderType>(someDependency: Injected<Builder.ObjectType>) -> Builder {
    return ConcreteBuilder(someDependency: someDependency)
}

具有相同的结果。我看到我只可以公开ConcreteBuilder,但我希望能够隐藏该实现细节。我在这里想念什么?

2 个答案:

答案 0 :(得分:1)

我不确定如何解决此问题,但问题的根源是newBuilder(someDependancy:)具有通用类型签名,但实际上不是通用的。

其返回类型断言该函数可以返回任何类型T: BuilderType where Builder.ObjectType == O的对象,但是显然不是这样。不支持要求此函数返回ConcreteBuilder以外的任何类型。充其量可以使用强制强制转换,但是如果有人编写let myBuilder: MyBuilder = ComplexObject.newBuilder(someDependancy: dec),则代码将崩溃(即使MyBuilder满足您的一般约束),因为您尝试强制强制强制ConcreteBuilderMyBuilder

就解决方案而言...我还没有。从根本上讲,您只想返回BuilderType,但我认为不可能,因为它具有关联的类型。

答案 1 :(得分:0)

这会吗?

return ConcreteBuilder(someDependency: someDependency) as! Builder