Swift Protocol Необязательное соответствие через Необязательное
У меня есть протокол с необязательным свойством.
Большинство типов, соответствующих этому протоколу, будут иметь соответствующее необязательное свойство. Однако у одного есть необязательное свойство того же типа и имени.
protocol SomeProtocol {
var foo: Int? { get }
}
struct StructA: SomeProtocol {
let foo: Int?
}
struct StructB: SomeProtocol {
let foo: Int // Type 'StructB' does not conform to protocol 'SomeProtocol'
}
Нажатие Xcode "Исправить - Вы хотите добавить заглушки протокола?" Кнопка добавляет необязательную версию свойства, но теперь в структуре есть недопустимые повторяющиеся имена переменных:
struct StructB: SomeProtocol {
let foo: Int
var foo: Int? { return foo } // Invalid redeclaration of 'foo'
}
В { get }
случае -only я предполагал, что это будет «просто работать» из-за того, что необязательное всегда удовлетворяет ограничениям необязательного, аналогично тому, как вы можете вернуть необязательное в функции с необязательным типом возвращаемого значения. Но, видимо, это не так.
То же самое работает и с функциями; протокол func bar() -> Int?
не удовлетворяется объявлением соответствующего типа func bar() -> Int
.
Есть ли способ обойти эту проблему? Я бы предпочел не переименовывать переменные и не добавлять промежуточные геттеры.
Рассматривалась ли такая ситуация для Swift? Что является рациональным в том, чтобы не позволять необязательному удовлетворять необязательной переменной протокола?
Ответы
Если протокол предоставляет реализацию по умолчанию, которая возвращает необязательный параметр:
protocol SomeProtocol {
var foo: Int? { get }
}
extension SomeProtocol {
var foo: Int? { return nil }
}
Типы, соответствующие протоколу, могут затем предоставить замещающую необязательную версию переменной / функции:
struct StructB: SomeProtocol {
let foo: Int
}
Я нашел это обсужденным на форуме Swift Evolution:
На первый взгляд я подумал, что есть правило, позволяющее удовлетворить требования протокола с необязательными типами, но это привело к ошибке. Только после дальнейшего исследования я заметил, что должна существовать реализация по умолчанию, чтобы «отчасти переопределить» требование необязательной версией.
https://forums.swift.org/t/how-does-this-rule-work-in-regard-of-ambiguity/19448
Эта команда Swift также обсуждает возможность соответствия необязательных типов протоколам с необязательными значениями:
Имеет ли смысл разрешать удовлетворение требований протокола с помощью необязательных типов, например, с ошибочными инициализациями? (Вероятно, с некоторым неявным необязательным продвижением.)
Да, конечно! За исключением той части, где это изменяет поведение существующего кода, поэтому нам следует быть очень осторожными с этим. Это считается частью [SR-522]. Функции протокола не могут иметь ковариантный возврат.
который отслеживается в Stack Overflow здесь:
Why can't a get-only property requirement in a protocol be satisfied by a property which conforms?