Возможно ли иметь только явное соответствие протоколу?

Обо всем по порядку. Поскольку я знаю, что это неизбежно, здесь есть похожий вопрос по этой же теме. Хотя тема одна и та же, ее назначение / использование отличаются по своему назначению. Таким образом, решение этого вопроса - не то же самое, что достижение того, что я здесь задаю. Поэтому, пожалуйста, прочитайте, что я пытаюсь решить, прежде чем пометить это как дубликат. Спасибо!

В Swift мы используем протоколы, которые похожи (но не совсем совпадают) с интерфейсами в других языках. Одна вещь, которую я видел в этих других языках, таких как C#, это возможность реализовать интерфейс как явно, так и явно. Мне интересно, есть ли у Свифта возможность последнего.

Вот концепция, показанная с использованием синтаксиса 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

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

0 ответов

Другие вопросы по тегам