У Swift я можу явно встановити тип змінної, оголосивши її наступним чином:
var object: TYPE_NAME
Якщо ми хочемо зробити крок далі і оголосити змінну, яка відповідає декільком протоколам, ми можемо використовувати protocol
декларатив:
var object: protocol<ProtocolOne,ProtocolTwo>//etc
Що робити, якщо я хотів би оголосити об’єкт, який відповідає одному або декільком протоколам, а також має певний тип базового класу? Еквівалент Objective-C буде виглядати так:
NSSomething<ABCProtocolOne,ABCProtocolTwo> * object = ...;
У Swift я би очікував, що це виглядатиме так:
var object: TYPE_NAME,ProtocolOne//etc
Це дає нам гнучкість можливості мати справу з реалізацією базового типу, а також доданим інтерфейсом, визначеним у протоколі.
Чи є інший більш очевидний спосіб, що я можу пропасти безвісти?
Приклад
Як приклад, скажімо, у мене є UITableViewCell
завод, який відповідає за повернення комірок, що відповідають протоколу. Ми можемо легко налаштувати загальну функцію, яка повертає клітинки, що відповідають протоколу:
class CellFactory {
class func createCellForItem<T: UITableViewCell where T:MyProtocol >(item: SpecialItem,tableView: UITableView) -> T {
//etc
}
}
пізніше я хочу зняти з комірок ці комірки, використовуючи як тип, так і протокол
var cell: MyProtocol = CellFactory.createCellForItem(somethingAtIndexPath) as UITableViewCell
Це повертає помилку, оскільки комірка подання таблиці не відповідає протоколу ...
Я хотів би мати можливість вказати, що комірка є a UITableViewCell
і відповідає MyProtocol
оголошенню змінної?
Виправдання
Якщо ви знайомі з Factory Pattern, це має сенс у контексті можливості повернення об'єктів певного класу, що реалізують певний інтерфейс.
Як і в моєму прикладі, іноді ми любимо визначати інтерфейси, які мають сенс у застосуванні до певного об'єкта. Мій приклад комірки подання таблиці - одне з таких обґрунтувань.
Незважаючи на те, що наданий тип не зовсім відповідає згаданому інтерфейсу, об'єкт, який повертає завод, відповідає, і тому я хотів би мати гнучкість у взаємодії як з базовим типом класу, так і з оголошеним інтерфейсом протоколу
NSSomething<ABCProtocolOne,ABCProtocolTwo> * object = ...;
. Цей об’єкт здається абсолютно марним, оскільки NSSomething
вже знає, з чим він відповідає. Якщо це не відповідає одному з протоколів у <>
вас, ви отримаєте unrecognised selector ...
збої. Це взагалі не забезпечує безпеку типу.