Я работал над учебником Рэя Вендерлиха и заметил, что автор использует расширения класса для хранения обратных вызовов делегата, а не для обработки их в самом классе, то есть:
делегировать обратные вызовы внутри расширения класса:
extension LogsViewController : UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
...
}
}
вместо того, чтобы содержать его в классе:
делегировать обратные вызовы внутри класса:
class LogsViewController : UITableViewController, UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
...
}
}
Я нашел это странным и интересным одновременно. У него есть файл, выделенный только для расширений в классе LogsViewController с именем «LogsViewControllerExtension.swift», и имеет разные расширения для каждого протокола делегата: UITableViewDataSource, UISplitViewDelegate и т. Д., Т.е.
несколько расширений классов каждый с делегатами обратных вызовов в своем собственном файле:
extension LogsViewController: UISplitViewControllerDelegate {
... callbacks
}
extension LogsViewController : UIPopoverPresentationControllerDelegate {
... callbacks
}
Почему?
Какие преимущества есть в этом? Я могу видеть, где это может быть немного более читабельным, чтобы отделить это, но в то же время это уровень косвенности. Существуют ли ОО-принципы, которые поддерживают или против этого?
источник
Ответы:
Я не знаю, почему вы сказали, что это добавляет уровень косвенности. Может быть, вы подразумеваете нечто иное, чем традиционное значение, потому что при этом не возникает никакой дополнительной косвенности. Но зачем это делать?
Я делаю это, потому что это более модульно. Весь код, который требуется интерфейсу, сгруппирован в одном месте (за исключением фактических свойств.) Если позже я решу создать отдельный класс для реализации этого протокола (и, таким образом, ввести фактический уровень косвенности), все, что мне нужно do - изменить расширение на собственный класс (пропуская необходимые свойства через функцию init) и создать свойство в ViewController для создания экземпляра объекта.
Я также поместил в расширение любые частные функции, которые используются только функциями этого протокола. Я не зашел так далеко, чтобы создать совершенно отдельный файл для расширения, но благодаря этому становится ясно, что эти частные функции предназначены только для этого протокола.
И, во всяком случае, люди часто жалуются на жирные контроллеры представления, и разбиение контроллера представления таким образом помогает поддерживать его более организованным, даже если это на самом деле не делает контроллер представления более тонким.
источник
Как сказал Даниил в отношении косвенности, его уровня нет.
Я согласен с ним, и я хотел бы добавить дополнительную мощную функцию расширений протокола, которую я знал недавно.
Скажем, у вас есть протокол,
didCopyText
например. Вы будете реализовывать это как:В Swift свойства и методы не реализованы в объявлении протокола, вы бы хотели записать реализацию в каждом классе, соответствующем
didCopyText
, с инкрементным числом классов, соответствующих этому протоколу с той же реализацией, это закончилось бы просто беспорядком повторный код. Вот где протокольные расширения пригодятся.С реализацией свойств протокола и методов. Теперь любой класс, соответствующий этому протоколу, будет использовать ту же реализацию.
источник
Допустим, ваш класс поддерживает три протокола, и поэтому вам нужно добавить три набора функций. Единственная цель этих функций - поддержка протокола, поэтому вам нужна документация.
Однако, если вы добавляете расширение для каждого протокола, и в каждом расширении вы реализуете именно те функции, которые необходимы для этого протокола, это делает ваш код намного более читабельным.
Я бы, скорее всего, не поместил их в отдельные файлы, если бы эти расширения не были действительно большими.
источник