ИЗМЕНИТЬ, чтобы ответить на изменение вопроса:
createTwo
не работает, потому что у вас такое же заблуждение, как я сказал в своем исходном ответе. createTwo
самостоятельно решил, что F
должен быть String
или Int
, а не «любым типом, который соответствует Fooable
».
Для createOne
у вас есть другой общий заблуждение. Generi c классы инвариантны . AnyFoo<String>
не является разновидностью AnyFoo<Fooable>
. На самом деле это совершенно не связанные типы! Подробнее см. здесь .
По сути, то, что вы пытаетесь сделать, нарушает безопасность типов, и вы переделываете свои API и выбираете другой подход.
Исходный ответ (для первоначального пересмотра вопроса)
Похоже, у вас распространенное неправильное представление о дженериках. Параметры Generi c определяются вызывающим, а не вызываемым.
В createOne
вы возвращаете anyFoo
, который имеет тип AnyFoo<Int>
, а не AnyFoo<P>
. Метод (вызываемый) решил, что P
должно быть Int
. Этого не должно происходить, потому что вызывающий решает, какими должны быть общие c параметры. Если вызываемый - generi c, он должен иметь возможность работать с любым типом (в пределах ограничений). В любом случае, P
не может быть здесь Int
, поскольку P: FooProtocol
.
Ваш метод createOne
вообще не должен быть общим c, так как он работает только с Int
:
func createOne() -> AnyFoo<Int> {
let anyFoo = AnyFoo(p: FooImpClass())
return anyFoo
}