在这种情况下我无法推断出什么类型?

时间:2019-04-29 12:53:54

标签: swift

我有一个协议:

protocol Model {}

使用此协议的结构:

struct Foo: Model {}

然后我有一个通用的协议:

protocol Controller {
    func fun<T: Model>() -> Observable<T>
}

控制器的方法实现可以推断出类型:

class Bar: Controller {
    func fun<Foo>() -> Observable<Foo> {
        // return an observable
    }
}

我以为我在这里做的是有两个“基本”协议,一个用于模型,一个用于控制器。基本控制器指示使用基本模型组的泛型实现的方法,然后实现可以指定要使用的模型。写完所有内容后,它可以正常编译,并且一切看起来都井井有条,但是当我创建Bar的实例并尝试对其调用fun()时,我会收到一条错误消息,提示Generic parameter 'Foo' can not be inferred。 > 这是一个可以复制的最小完整示例:

protocol Model {}

struct Foo: Model {}

protocol Controller {
    func fun<T: Model>() -> Observable<T>
}

class Bar: Controller {
    func fun<Foo>() -> Observable<Foo> {
        return Observable.create { observer in

            let cancel = Disposables.create {
                // clean up
            }

            return cancel
        }
    }
}

现在调用Bar().fun()会出现错误:Generic parameter 'Foo' can not be inferred

有两件事我在这里不明白。首先是它怎么知道我调用了指定Foo的实现,而同时又无法推断类型呢? Foo不是通用的,它是Foo结构的实际类型。我不明白的第二件事和这里的实际问题是,如果我在实现并指定通用方法的实例上调用方法,为什么它不能推断类型

3 个答案:

答案 0 :(得分:1)

我认为您的误解是将这种方法中的Foo误认为是Foo结构:

func fun<Foo>() -> Observable<Foo> {
    // return an observable
}

不是!在以上方法的上下文中,Foo只是另一个通用类型参数!


您要在这里实现的目标...

  

基本控制器使用基本模型组的泛型来指定要实现的方法,然后实现可以指定要使用的模型。

...应使用关联的类型:

protocol Model {}

struct Foo: Model {}

protocol Controller {
    associatedtype ModelType: Model
    func fun() -> Observable<ModelType>
}

class Bar: Controller {
    typealias ModelType = Foo
    func fun() -> Observable<Foo> {
        return Observable.create { observer in

            let cancel = Disposables.create {
                // clean up
            }

            return cancel
        }
    }
}

答案 1 :(得分:0)

    func fun<Foo>(_ type: Foo.Type) -> Observable<Foo> {
        return Observable.create { observer in

            let cancel = Disposables.create {
                // clean up
            }

            return cancel
        }
    }

然后您可以通过以下方式调用它:

Bar.fun(YourModel.self)

答案 2 :(得分:0)

首先,您需要修复fun方法的实现:

class Bar: Controller {
    func fun<T: Model>() -> Observable<T> {
        return Observable<T>.create { observer in

            let cancel = Disposables.create {
                // clean up
            }

            return cancel
        }
    }
}

然后,您需要在调用方中推断出通用的Foo参数,例如:

let observableFoo: Observable<Foo> = Bar().fun()
相关问题