Я не думаю, что это проблема с вашим пониманием связанных типов, так же как и с дженериками.Обобщения не ковариантны;нет принципа замещения для параметризованных типов.Другими словами, то, что вы можете мысленно вставить D
вместо Self
, не означает, что вы можете заменить C<D>
на C<Self>
.Это разные типы (не связанные).
Вот простой контрпример, чтобы показать вам, что я имею в виду:
class C<T> {
init(arg: T) {}
}
class Cat {}
class Kitten : Cat {}
Теперь давайте попробуем использовать C<Kitten>
, где ожидается C<Cat>
:
var c1 = C(arg:Cat())
var c2 = C(arg:Kitten())
c1 = c2 // error
Я подозреваю, что , что - это то, что, по вашему мнению, должно работать.Это не так.По той же причине ваша вера в то, что «C<D>
должен быть того же типа, что и C<Self>
», неверна.
Чтобы сделать это немного более релевантным вашему фактическому примеру, рассмотрим этот тривиальный случай.Это компилирует:
class C<T> {
init(arg: T) {}
}
protocol P {
associatedtype A: C<Any>
func foo(_ x: A)
}
struct D: P {
func foo(_ x: C<Any>) {}
}
Но это не компилируется:
class C<T> {
init(arg: T) {}
}
protocol P {
associatedtype A: C<Any>
func foo(_ x: A)
}
struct D: P {
func foo(_ x: C<String>) {}
}
Ну, вы можете сказать, что String - Any, так почему же этот компилятор не компилируется?Это потому, что этот факт не имеет значения;в параметризованном типе нет универсального принципа замещения.