Какой мой тип не заразен в этом случае? - PullRequest
1 голос
/ 29 апреля 2019

У меня есть протокол:

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 ]

1 голос
/ 29 апреля 2019

Я думаю, что ваше недоразумение состоит в том, что вы ошибочно принимаете Foo в этом методе как Foo struct:

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
        }
    }
}
0 голосов
/ 29 апреля 2019

Во-первых, вам нужно будет исправить реализацию метода 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()
0 голосов
/ 29 апреля 2019
    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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...