Как работает дополнительная ковариация в Swift
Как ковариация работает для Optional
в Swift?
Скажем, я пишу следующий код:
var nativeOptionalView: Optional<UIView>
let button = UIButton()
nativeOptionalView = .Some(button)
var nativeOptionalButton = Optional.Some(button)
nativeOptionalView = nativeOptionalButton
Он компилируется и работает отлично. Однако, если я определяю MyOptional
как
enum MyOptional<T> {
case Some(T)
case None
}
И напишите следующее:
var myOptionalView: MyOptional<UIView>
let button = UIButton()
myOptionalView = .Some(button)
var myOptionalButton = MyOptional.Some(button)
myOptionalView = myOptionalButton
Я получаю сообщение об ошибке:
error: не может назначить значение типа 'MyOptional<UIButton>
' для ввода 'MyOptional<UIView>
'
Я понимаю, почему эти ошибки происходят с MyOptional
, я не понимаю, почему это не происходит с Optional
.
Ответы
Ответ 1
Это не так. На данный момент Swift не поддерживает специальные ковариантные дженерики.
Проверка типа Swift - это выражение, а не глобальное (как в Haskell). Эта задача обработана семантическим анализом в lib/Sema. Затем система ограничений пытается соответствовать типам, а затем обрабатываются специальные случаи ковариации для и optionsals.
Это было решение для языкового дизайна. Вы должны иметь возможность делать все, что вам нужно, с помощью встроенных типов коллекций и опций. Если вы этого не сделаете, вам следует открыть радар.
Ответ 2
В то время как я согласен с тем, что, вероятно, существует какая-то "магия компилятора", это может быть выполнено в вашей пользовательской реализации путем нажатия кнопки на UIView, например.
var myOptionalButton = MyOptional.Some(button as UIView)
или
var myOptionalButton: MyOptional<UIView> = .Some(button)