iOS ›› Протоколы и делегаты

В сети много материалов о Protocols & Delegates, а в разных туториалах некоторые "участники" процесса называются по-разному.

особенно запутанными являются концепции «Адаптер» и «Конформер».

Я понимаю, что класс, который реализует методы протокола, то есть тот, в котором есть оператор <ProtocolName>, является «соответствующим протоколу». Является ли он также «Принимающим» протокола?

Как мне вызвать класс, в котором протокол объявлен или повторно объявлен, чтобы он мог включать свойство, которое должно соответствовать протоколу, т. е. иметь в своем интерфейсе оператор @protocol ProtocolName?

Я не смог найти никакой официальной документации Apple, объясняющей это.

ИЗМЕНИТЬ

Ребята, спасибо за указанные ответы, но я понимаю (и понимал) шаблон и то, как он реализован в языке. Мои проблемы были (и остаются) связанными с НАЗВАНИЕМ... и тем не менее, я не смог найти никакой ссылки на то, "как называется (концептуально) класс, который ОБЪЯВЛЯЕТ/ПОВТОРЯЕТ ОБЪЯВЛЕНИЕ протокола". Может быть, у него нет имени, и я должен назвать его просто: «Класс, в котором объявлен/переобъявлен протокол». Может быть, я могу назвать это «Класс делегирования» (кстати, звучит неплохо)…


person Ohad Regev    schedule 27.11.2013    source источник
comment
Я никогда не слышал, чтобы их называли «адоптерами» или «конформерами». Я слышал утверждение «Соответствует протоколу» раньше, но я всегда знал их, и во всем, что я читал, они всегда упоминались как «протоколы». Вероятно, это просто быть, но если они ссылаются на них как на что-то другое, то они, вероятно, не очень хорошие учебники, и я бы держался от них подальше. Если вы пишете учебник, вы не должны использовать терминологию, которую никто не знает. Это Протоколы и Делегаты, которыми они и должны называться.   -  person Popeye    schedule 27.11.2013
comment
@Охад Регев. Я не уверен, что это является источником путаницы, поэтому извините, если вопрос вас обидит, знаете ли вы, что adopt и adapt — разные английские слова?   -  person ilya n.    schedule 27.11.2013
comment
Илья, ну тут я ошибся, и я понимаю разницу между этими словами... но спасибо за поправку... Так или иначе, остается вопрос - какой класс является АДОПТЕРОМ... и что более важно ( если это не усыновитель), как мне вызвать класс, в котором протокол был объявлен/переобъявлен, - это тот, где фактически вызываются методы (в то время как делегат функционирует как получатель методов).   -  person Ohad Regev    schedule 27.11.2013


Ответы (5)


Семантика. Я бы сказал, его действие против результата.

Принимая протокол (действие), вы соблюдаете его (результат).

person fguchelaar    schedule 27.11.2013

Протоколы

Говоря о Objective-C, протокол — это понятие языка Objective-C, поэтому его может понять компилятор. В частности, вы можете определить его по ключевому слову @protocol.

Класс может объявить себя соответствующим протоколу с синтаксисом угла:

 @interface MyClass <MyProtocol> // class MyClass conforms to protocol MyProtocol

Некоторые люди используют здесь слово принять, например, «класс MyClass принимает протокол MyProtocol».

Этот синтаксис будет понятен компилятору Objective-C, например, он может предупредить вас, если в MyProtocol есть обязательные методы, которые не реализованы в MyClass.

Узоры

(Дизайн программирования) Шаблоны – это абстрактные понятия, которые могут быть реализован на любом языке (полном по Тьюрингу). Вы пишете код для конкретного языка, а затем рассказываете людям об этом шаблоне. Компилятор не будет знать, назвали вы код каким-то модным словом или нет.

Адаптер — это особый шаблон. Его, опять же, можно использовать с любым языком программирования, хотя некоторые языки, например. Python упрощает это с помощью объявлений.

Я не знаком с концепцией Conformer.

Делегаты

Делегирование является частью шаблона делегирования. Он используется для решения проблемы, когда объект A хочет что-то сделать с объектом B, а затем хочет, чтобы B мог поговорить с A. Чтобы сделать этот разговор возможным, B нужно будет кое-что знать о методах A, но если A очень сложный класс, то B может быть вынужден знать "слишком много".

Шаблон делегирования решает эту проблему, явно объявляя протокол DelegateOfB, определенный там, где определен B. Затем любой класс, которому необходимо получить информацию от B (например, A), объявляет, что он соответствует DelegateOfB, и реализует соответствующие методы. Следовательно, B ничего не знает о A, кроме того факта, что он соответствует DelegateOfB.

Этот шаблон также может быть реализован на любом языке, но Cocoa/Cocoa Touch или большинство других сред Objective-C необычны тем, что делегирование используется в 90% случаев всякий раз, когда возникает вышеупомянутая проблема.

Здесь помогает то, что протоколы являются языковой функцией. Опять же, этот шаблон теоретически можно использовать на любом языке, даже на ассемблере :), но он будет более полезен для Objective-C, потому что вы можете объявить, что делегат должен соответствовать этому протоколу:

@property id<DelegateOfB> delegate;

и компилятор предупреждает вас, если он думает, что вы присваиваете что-то, что не соответствует DelegateOfB.

В других языках обычно используются другие решения, такие как функции обратного вызова.

person ilya n.    schedule 27.11.2013

Обратитесь к сообщению.

Протокол, объявленный с синтаксисом (@protocol в Objective-C), используется для объявления набора методов, которые будет реализовывать класс, который "принимает" (заявляет, что будет использовать этот протокол). Это означает, что вы можете указать в своем коде, что «вам все равно, какой класс используется, если он реализует определенный протокол». Это можно сделать в Objective-C следующим образом:

id<MyProtocol> instanceOfClassThatImplementsMyProtocol;

Если вы укажете это в своем коде, то любой класс, "соответствующий" протоколу MyProtocol, может быть использован в переменной instanceOfClassThatImplementsMyProtocol. Это означает, что код, который использует эту переменную, знает, что он может использовать любые методы, определенные в MyProtocol с этой конкретной переменной, независимо от того, к какому классу она относится. Это отличный способ избежать шаблона проектирования наследования и тесной связи.

Делегаты — это использование языковой функции протоколов. шаблон проектирования делегирования — это способ разработки вашего кода для использования протоколов там, где это необходимо. В рамках Cocoa шаблон проектирования делегата используется для указания экземпляра класса, который соответствует определенному протоколу. Этот конкретный протокол определяет методы, которые должен реализовать класс делегата для выполнения определенных действий при заданных событиях. Класс, который использует делегат, знает, что его делегат соответствует протоколу, поэтому он знает, что может вызывать реализованные методы в заданное время. Этот шаблон проектирования является отличным способом разделения классов, потому что он позволяет очень легко заменить один экземпляр делегата на другой — все, что нужно сделать программисту, — это убедиться, что замещающий экземпляр или класс соответствует необходимому протоколу (т. е. он реализует методы, указанные в протоколе)!

Протоколы и делегаты не ограничиваются только разработкой на Objective-C и Mac/iOS, но язык Objective-C и платформы Apple широко используют эту замечательную языковую функцию и шаблон проектирования.

Вот пример. В структуре UIKit Cocoa Touch есть протокол UITextFieldDelegate. Этот протокол определяет ряд методов, которые должны реализовывать классы, являющиеся делегатами экземпляра UITextField. Другими словами, если вы хотите назначить делегата UITextField (используя свойство делегата), вам лучше убедиться, что этот класс соответствует UITextFieldDelegate. Фактически, поскольку свойство делегата UITextField определяется как:

@property(nonatomic, assign) id<UITextFieldDelegate> delegate

Тогда компилятор выдаст предупреждения, если вы назначите ему класс, который не реализует протокол. Это действительно полезно. Вы должны заявить, что класс реализует протокол, и говоря, что это так, вы сообщаете другим классам, что они могут определенным образом взаимодействовать с вашим классом. Таким образом, если вы назначаете экземпляр MyTextFieldDelegateClass свойству delegate элемента UITextField, UITextField знает, что он может вызывать определенные методы (относящиеся к ввод текста, выделение и т. д.) вашего MyTextFieldDelegateClass. Он знает это, потому что MyTextFieldDelegateClass заявил, что будет реализовывать протокол UITextFieldDelegate.

В конечном итоге все это приводит к гораздо большей гибкости и адаптивности кода вашего проекта, что, я уверен, вы скоро поймете после использования этой технологии! Наслаждаться :)

person Vinay Jain    schedule 27.11.2013
comment
Если вы скопируете ответ из другого вопроса, вы можете рассмотреть возможность назвать источник. Красиво скопировано из: stackoverflow.com/questions/17192287/ - person fguchelaar; 27.11.2013

Здесь Programming With Objective-C Apple doc, в котором кратко изложены термины, которые вы ищете, такие как принятие и соответствие и т. д.

person Suryakant Sharma    schedule 27.11.2013
comment
Пожалуйста, попробуйте добавить дополнительную информацию о вашей ссылке, в случае неработающей ссылки ваш ответ будет совершенно бесполезен :) - person Edelweiss; 27.11.2013

Я не совсем уверен, что вы спрашиваете. Но вы можете заставить класс, использующий ваш протокол, реализовать определенный метод.

@protocol theDelegate <NSObject>

@required
-(void)doSomething;
@end
person Mikael    schedule 27.11.2013