Swift - Почему протокол все еще рассматривается как универсальный, даже если в предложении where указан специализированный тип? - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть общий протокол:

protocol GenericProtocol {
  associatedtype GenericParameter
}

Я не могу использовать это так:

var someValue: GenericProtocol?

Я получаю сообщение об ошибке, которое мы все хорошо знаем:

Протокол 'GenericProtocol' может использоваться только в качестве общего ограничения, поскольку он имеет требования к Self или связанный тип

Много раз столкнувшись с этой ошибкой и потратив долгое время на размышления над концептуальной причиной этой ошибки, я думаю, что я по крайней мере несколько понял ее. Чего я не понимаю, так это того, почему я не могу создать протокол, который наследует и специализирует мой универсальный протокол так, чтобы его можно было использовать в сигнатурах типов. Вот протокол наследования:

protocol ConcreteProtocol: GenericProtocol where GenericParameter == Bool { }

Но даже это я не могу использовать в сигнатуре типа:

var someValue: ConcreteProtocol?

Протокол 'ConcreteProtocol' может использоваться только в качестве общего ограничения, поскольку он имеет требования к Self или связанный тип

Не понимаю ли я, что означает where? Какова концептуальная причина того, что даже ограниченные подпротоколы должны рассматриваться как общие? Я уверен, что это не ошибка, а скорее целенаправленный факт языка, известного сообществу Swift. Кто-нибудь может мне это объяснить?

Также, если бы кто-нибудь мог предоставить способ, которым я могу достичь того, чего я хочу, это было бы очень ценно, хотя я не уверен, что это возможно.

1 Ответ

0 голосов
/ 06 сентября 2018
var someValue: GenericProtocol?

Почему это не работает, совершенно очевидно, если вы подумаете о попытке

var someValue: Class = Class1()
someValue            = Class2()

Дело в том, что у вас есть протокол, который для каждого типа, который вы назначаете, отличается, например, имеет разные типы методов, что делает someValue непригодным для использования.

protocol ConcreteProtocol: GenericProtocol where GenericParameter == Bool { }
var someValue: ConcreteProtocol?

скорее всего не работает, потому что классы могут захотеть переопределить associatedtype и поэтому не могут быть назначены на someValue. Поэтому реализация этого в языке, вероятно, будет запрещать переопределению классов, поскольку ConcreteProtcol может уже использовать GenericParameter == Bool в одном из своих расширений.

...