Перво-наперво.Поскольку я знаю, что это неизбежно, здесь есть похожий вопрос по этой же теме.Хотя тема та же самая, обоснование / использование ее отличается по своему намерению.Таким образом, решение этого вопроса - не то же самое, что достижение того, что я здесь задаю.Поэтому, пожалуйста, прочитайте то, что я пытаюсь решить, прежде чем пометить это как дубликат.Спасибо!
В Swift мы используем протоколы, которые похожи (но не совсем совпадают) с интерфейсами в других языках.Одна вещь, которую я видел в этих других языках, таких как C #, - это способность реализовывать интерфейс неявно и явно.Мне интересно, имеет ли Swift возможность последнего.
Вот концепция, показанная с использованием синтаксиса Swift.Обратите внимание, что это не скомпилируется.Это только для иллюстрации.
protocol DateSortable{
var sortDate:Date { get }
}
struct OrderedItem : DateSortable {
// Implicit conformance because the name sortDate matches the protocol
let sortDate:Date
}
struct Invoice : DateSortable {
let invoiceDate:Date
// Explicit conformance - Note you must specify the protocol name
// Additionally, you cannot access 'invoice.sortDate' directly
// You must cast to 'DateSortable' first
var DateSortable.sortDate:Date { return invoiceDate }
}
let someDate = orderedItem.sortDate // Allowed
let someOtherDate = invoice.sortDate // *NOT* Allowed
let antherDate = (invoice as! DateSortable).sortDate // Allowed
Опять же, приведенный выше псевдокод, но иллюстрирует, как другие языки поддерживают эту функцию.
Преимущества и преимущества явного соответствия
Первое преимущество явного соответствия состоит в том, что вы можете соответствовать протоколу, не загромождая собственный интерфейс.
Например, если у вас есть десять протоколов, которые все определяют дату, которая функционально соответствует датеу вас есть в вашей модели, но они используют десять различных имен для нее, явное соответствие позволит вам соответствовать всем десяти, без необходимости публично выставлять эти десять различных имен в вашем интерфейсе.(т. е. выше, Invoice
предоставляет только invoiceDate
напрямую, даже если он соответствует DateSortable
, что предполагает sortDate
.)
Второе преимущество заключается в том, что он защищает вас от конфликтов имен членов.
Рассмотрим два несвязанных протокола, скажем Orderable
и Deliverable
, которые, к сожалению, выбрали одно и то же имя для своего члена, var date:Date{ get }
, и они не принадлежат вам.Они находятся в используемой вами среде.
Теперь в вашей собственной PurchaseItem
модели у вас есть и orderDate
и deliveryDate
.Явное соответствие могло бы решить эту проблему, например, так ...
extension PurchaseItem : Orderable {
var Orderable.date:Date { return orderDate }
}
extension PurchaseItem : Deliverable {
var Deliverable.date:Date { return deliveryDate }
}
Короче говоря, явные объявления интерфейса позволяют связывать вещи по функциональности, а не только по имени.Вы все равно можете связать их по имени, если хотите, поскольку это автоматически, но это больше не является обязательным требованием.
Итак, есть ли у Swift что-то похожее на приведенное выше?
Закрыть, но не совсем!
Самое близкое, что я могу придумать, - это частное расширение, добавляющее соответствие этому протоколу на сайте, где он необходим, например ...
private extension Invoice : DateSortable {
var DateSortable.sortDate:Date { return invoiceDate }
}
let someDate = invoice.sortDate // Only valid in the scope of this extension
Однако у этого подхода есть ограничения и предостережения , как видно здесь .Конечно, потребность в этом вопросе иная, но предостережения остаются прежними.