Колбэк что это в кастинге
Перейти к содержимому

Колбэк что это в кастинге

  • автор:

Колыбельные песни для детей на украинском языке: видео и тексты

Колыбельная для детей на украинском языке: тексты песен и видео

Все родители хорошо знают: колыбельная всегда помогает малышу быстрее заснуть. Поэтому мы подобрали 5 песен для детей на украинском языке, которые могут пригодиться новоиспеченным мамочкам и папочкам.

Поделиться

Почему важно петь детям колыбельные

Как сообщает 24 канал со ссылкой на комментарий психолога Алины Томин, колыбельные необходимы не только младенцам, но и детям разного возраста. Часто будущие мамы напевают их еще до рождения малыша и так успокаивают его, позволяют привыкнуть к голосу и распознавать его. Поэтому благодаря колыбельным между мамой и ребенком возникает особая связь, которую можно сохранить на протяжении всей жизни.

Кроме этого, мамино пение влияет и на поведение детей после их рождения. Об этом свидетельствуют и многочисленные исследования.

Колыбельная – признак того, что мама рядом и ребенок находится под защитой. Это дает ему ощущение заботы, покоя, настраивает на крепкий и здоровый сон. Дети, которым поют колыбельные перед сном, являются менее тревожными, а также более уравновешенными и спокойными,
– рассказала Алина Томин.

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

До какого возраста стоит петь колыбельные

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

5 колыбельных на украинском языке

«Ой ходить сон коло вікон»

Текст колыбельной

Ой ходить сон коло вікон,
А дрімота – коло плота.
Питається сон дрімоти:
– А де будем ночувати?

– Де хатонька теплесенька,
Де дитина малесенька, –
Там ми будем ночувати,
Дитиночку колихати.

Ой на кота та воркота,
На дитину та й дрімота,
Котик буде воркотати,
Дитинонька буде спати.

Слушайте колыбельную «Ой ходить сон коло вікон» в исполнении Нины Матвиенко: видео

«Ніченька іде»

Текст колыбельной

Гойда, гойда-гой, ніченька іде,
Діточок малих спатоньки кладе.
Під вікном тремтить вишенька мала,
В хатку проситься, бо прийшла зима.
Під вікном тремтить вишенька мала,
В хатку проситься, бо прийшла зима.

Гойда, гойда-гой, очка заплющи,
В сні щасливому зогрієшся ти.
Йди до хлопчика, люба вишенько,
В колисочці вам буде тепленько.
Йди до хлопчика, люба вишенько,
В колисочці вам буде тепленько.

Гойда, гойда-гой ніч прийшла до нас,
Діточкам малим спатоньки вже час.
Рости, хлопчику, з вишенькою враз,
Хай не скупиться доленька для вас.
Рости, хлопчику, з вишенькою враз,
Хай не скупиться доленька для вас.

Слушайте колыбельную «Ніченька іде» в исполнении Нины Матвиенко: видео

«Сонько-дрімко»

Текст колыбельной

Пізня вже годинка,
Чом не спиш, дитинко?
Он твоя матуся
Кличе Сонька-дрімка.

На котячих лапках
Сонько-дрімко ходить.
Каже він малятам:
«Пустувати годі!»

Гра закінчилась,
Матінка втомилась
В ліжко лягай,
Швидше засинай.

Сонько-дрімко носить
Всім, хто лиш попросить,
В кошику лозовім
Казочки чудові.

Принесе співанку,
Тиху колисанку.
Хто її послуха –
Спатиме до ранку.

Синку маленький, донечко рідненька,
Нічка прийшла, спатоньки пора.

Завтра Сонько-дрімко
Прийде в кожну хату.
Знову наших діток
Буде колисати.

Слушайте колыбельную «Сонько-дрімко»: видео

«Вечірня пісня»

Текст колыбельной:

Тихесенький вечір на землю спадає,
І сонце сідає в темнесенький гай.
Ой сонечко ясне, невже ти втомилось,
Чи ти розгнівилось? Іще не лягай!

Світи ще годину, бо рано ще спати,
Милуй нас, як мати, теплом обгортай!
Ой сонечко ясне, невже ти втомилось,
Чи ти розгнівилось? Іще не лягай!

Без тебе так страшно і темно надворі,
Хоч місяць і зорі освітять наш край.
Ой сонечко ясне, невже ти втомилось,
Чи ти розгнівилось? Іще не лягай!

Не слухає сонце, за гору сідає
І нам посилає на всю ніч: прощай!
Ой сонечко ясне, невже ти втомилось?
Чи ти розгнівилось? Іще не лягай!

Слушайте колыбельную «Вечірня пісня»: видео

«Котику сіренький»

Текст колыбельной:

Котику сіренький, котику біленький,
Котку волохатий, не ходи по хаті.
Не ходи по хаті, не буди дитяти.
Дитя буде спати, котик воркотати.

Ой, на кота на воркота,
На дитинку дрімота

Ой, ну люлі, котку, не йди на колодку,
Не йди на колодку, бо заб’єш головку.
Та буде боліти, нічим завертіти

Ой, на кота на воркота,
На дитинку дрімота

Слушайте колыбельную «Котику сіренький»: видео

Виды лабораторной посуды и для чего она нужна

Лабораторная посуда — это специализированные емкости и приспособления, обладающие устойчивостью к воздействию агрессивной среды. Используются при проведении исследовательских, научных и опытных работ.

  • термоустойчивость;
  • небольшой коэффициент теплового расширения;
  • устойчивость к воздействию химических препаратов и реагентов;
  • во многих случаях — прозрачность;
  • устойчивость к повышенному давлению.

Перед использованием посуду необходимо подготовить:

  • тщательно вымыть;
  • просушить;
  • по мере необходимости — провести стерилизацию.

Не допускается использование посуды:

  • не по назначению;
  • имеющей сколы и другие дефекты;
  • со следами химических препаратов и другими загрязнениями.

Лабораторная посуда изготавливается в соответствии со строгими нормами ГОСТ и должна отвечать всем правилам безопасности.

ГОСТ — установленные государственные стандарты и точно прописанные требования к качеству производимой продукции. Термин появился в СССР и дословно обозначал «Государственный общесоюзный стандарт». В настоящее время стандарты утверждаются на Межгосударственном совете по стандартизации в рамках деятельности СНГ — Содружества Независимых Государств.

Уход за посудой

Остатки химических реагентов, а также моющих веществ могут повлиять на результаты анализов и химических исследований. Поэтому при уходе за лабораторной посудой необходимо четко следовать установленным инструкциям.

  • твердые осадки и загрязнения удаляются механически;
  • для веществ, не растворяющихся в воде, используют органические растворители;
  • белковые вещества удаляются гидроокисью натрия или калия;
  • для более глубокой очистки используют синтетические моющие смеси на основе солей хрома, кислот и другие;
  • при мытье изделий из пластика нельзя использовать сильные растворы кислот и щелочей;
  • существуют специальные механические аппараты для очистки и сушения лабораторной посуды, перед их использованием необходимо тщательно ознакомиться с описанием правил работы.

Классификация лабораторной посуды

Лабораторная посуда различается по:

  • размерам;
  • сферам применения;
  • материалам, из которого изготовлена.

Наиболее распространенной является классификация посуды по ее целевому назначению:

  1. Общего назначения.
  2. Мерная.
  3. Специального назначения.

Наиболее часто используемые типы, перечень с названиями

Общего назначения

Это посуда широкого спектра применения. Чаще всего она используется в следующих процессах:

  • нагревание;
  • охлаждение;
  • смешивание;
  • проведение химических реакций;
  • хранение.
  1. Банки и бутыли — сосуды цилиндрической формы с крышкой. Банки имеют широкое отверстие сверху, бутыли — длинную горловину и узкое отверстие. Изготавливаются из стекла, а также химически стойких полимеров. Бывают прозрачные, затемненные и непрозрачные. Предназначены для хранения химических реагентов и препаратов.
  2. Бюксы — маленькие баночки с притертой пробкой. Чаще всего применяются, когда необходимо взвешивание сыпучего материала с его предварительным высушиванием. Конструкция емкости позволяет избежать увеличения веса вещества из-за впитывания водяных паров из воздуха. В качестве материала для бюксов используется стекло, пластик, алюминий, керамика.
  3. Воронки — приспособления с суживающимся концом, служащие для переливания жидкостей и пересыпания порошков. Существуют лабораторные воронки с гладкими и складчатыми фильтрами, делительные — для разделения несмешивающихся жидкостей и другие разновидности.
  4. Колбы — технические стеклянные сосуды с широким дном, сужающиеся кверху. Чаще всего имеют длинное узкое горло. Дно может иметь плоскую, круглую или коническую форму. Используют при проведении химических реакций.
  5. Кристаллизаторы — широкие чаши для выпаривания растворов и очистки веществ путем перекристаллизации. Бывают с носиком и без, обычные и термоустойчивые. В качестве материала для кристаллизаторов чаще всего используют стекло, фарфор или полипропилен. Должны иметь достаточно большой диаметр и плоское дно, поскольку это обеспечивает равномерность охлаждения раствора.
  6. Ложки, лопатки и шпатели — служат для взятия сыпучих и твердых веществ, а также для перемешивания жидкостей. Шпатели имеют плоскую форму, ложки — закругленный конец. Чаще всего бывают стеклянные и фарфоровые.
  7. Пробирки — сосуды в форме цилиндра с полукруглым, коническим или плоским дном. Используются для отбора проб и при проведении химических реакций. Чаще всего изготавливаются из боросиликатного или другого лабораторного стекла. В последнее время получили распространение также пробирки из специализированного пластика.
  8. Склянки — стеклянные емкости цилиндрической формы с плоским дном и горловиной под пробку. В них хранят химические вещества, в том числе летучие и пахучие. Герметичность хранения обеспечивается за счет притертой пробки, которая плотно вставляется в горловину. Для препаратов, чувствительных к свету, используют затемненные банки из стекла янтарного цвета.
  9. Ступки — применяются для измельчения и перемешивания твердых веществ. Бывают с носиком и без. Чаще всего изготавливаются из фарфора.
  10. Штативы — лабораторные стойки, использующиеся для размещения пробирок, колб, бюреток и другой лабораторной посуды на заданной высоте. Применяются при выполнении различных операций. Примеры: нагревание, перегонка веществ, химический синтез. Состоят из металлического основания и штанги, на которую устанавливаются крепежные элементы. Основание изготавливают из чугуна и покрывают влагоустойчивой порошковой краской. Материалом для штанги чаще всего служит нержавеющая сталь. Для соблюдения техники безопасности необходимо, чтобы все фиксирующие приспособления были размещены с точным расчетом. Это обеспечивает удобный доступ к лабораторной посуде и оставляет пространство для манипуляций.

Кристаллизатор. Источник: aredi.ru

Мерная посуда

К ней относится лабораторная посуда, которая преимущественно используется для точного определения объемов химических веществ, чаще всего — жидкостей.

  1. Бюретки — узкие градуированные сосуды для определения небольших объемов газа или жидкости. Представляют собой тонкие стеклянные трубки с нанесенными на стенки делениями. На одном конце трубке размещается зажим или запорный кран. Используются при титровании. Это один из распространенных методов аналитической химии по измерению объема раствора известной концентрации.
  2. Колбы мерные — сосуды со сферическим основанием и плоским дном, предназначенные для приготовления и разбавления стандартных растворов. По ГОСТу делятся на 2 класса точности: «А» — особой точности, «Б» — обычной точности. Изготавливаются из стекла, реже — из пластика. Матовым квадратом на стенке маркируются термоустойчивые мерные колбы.
  3. Мензурки — мерные емкости конической формы с сужающимся основанием. Название происходит от латинского слова «mensura» — «мерка, мера». Применяются для измерения жидкостей, реже — сыпучих веществ. Также используются для отделения жидкости от осадка. Материалом для мензурок служит термоустойчивое и химически инертное стекло, фарфор или пластик. Бывают разными по объему. Наиболее часто встречаются: 50, 100 и 250 миллилитров.
  4. Мерные цилиндры — мерные стаканы, по своему функциональному значению близкие к мензуркам, но имеющие цилиндрическую форму. На стенки цилиндра нанесена равномерная шкала делений. Объем цилиндров варьирует от 5 по 2000 миллилитров. Обладают большей точностью, чем мензурки.
  5. Пипетки — дозирующие маленькие сосуды, представляющие собой трубки с наконечником, ограничивающим скорость вытекания жидкости. Традиционно изготавливаются из стекла. В последнее время также всё чаще применятся пипетки из полимеров. Существует много видов лабораторных пипеток: градуированные и неградуированные, больших и малых объемов, оснащенные резиновыми грушами с клапаном и механическими регуляторами. Для измерения объемов меньше 1 миллилитра используют микропипетки. Одной из разновидностей являются газовые пипетки. Они снабжены зажимами с краном. Пример использования: взятие проб воздуха.

Мензурки. Источник: ssci-ltd.ru

Специального назначения

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

  1. Дистилляторы — приборы, которые используются для получения воды разной степени очистки путем ее перегонки. Под перегонкой понимают процесс испарения жидкости с ее последующим охлаждением и конденсацией паров.
  2. Дефлегматоры — устройства для конденсации паров жидкостей при перегонке и ректификации. Ректификация — разделение жидкостей на компоненты.
  3. Специализированные воронки — применяются для фильтрования жидкостей в конкретных процессах. Пример: воронка Бюхнера чаще всего используется для вакуумного фильтрования. Представляет собой фарфоровую воронку с множеством отверстий. При работе отверстия закрывают бумажным фильтром. Воронка Бюхнера через приемный сосуд подсоединяется к линии вакуума или водоструйному насосу. Для обеспечения герметичности используются резиновые пробки.
  4. Капельницы — предназначены для капельного дозирования невязких жидкостей. Разновидности: капельница Шустера — с боковым горлышком и длинным наконечником в виде клюва; капельница Страшейна — с притертой пробкой-пипеткой.
  5. Колбы специального назначения — колбообразные сосуды, применяемые в конкретных химических процессах. Колба Вюрца — емкость с круглым дном и боковым отводом. Используется для перегонки жидкостей при атмосферном давлении. Колба Энглера — разновидность колбы Вюрца с удлиненной горловиной. Служит для отделения фракций нефти и нефтепродуктов. Колба Бунзена — коническая колбы с плоским дном, применяемая в процессе вакуумного фильтрования.
  6. Тигли — термоустойчивые сосуды в виде чаши, применяющиеся для нагрева, прокаливания, высушивания и сплавления разных материалов. Чаще всего изготавливаются из фарфора.
  7. Чаши Петри — прозрачные невысокие сосуды цилиндрической формы с крышкой. По внешнему виду напоминают блюдца. Изготавливаются из стекла или полистирола. Обычно имеют диаметр от 50 до 100 миллиметров, высоту — 15 мм. В биологии используются для культивирования микроорганизмов, в химии — для хранения мелких фрагментов препаратов и испарения жидкостей.
  8. Эксикаторы — толстостенные стеклянные сосуды, которые служат для высушивания различных веществ и их хранения. Содержат плотно прилегающую пришлифованную стеклянную крышку, обеспечивающую герметичность. На дно эксикатора помещаю влагопоглощающее вещество, обеспечивающее определенную влажность воздуха, обычно близкую к нулю. По внешнему виду напоминают прозрачную кастрюлю. Иногда изготавливаются из пластика.

Эксикатор. Источник: pcgroup.ru

Названия специализированной лабораторной посуды часто содержат фамилии ученых, ее придумавших. Например:

  • Эрнст Бюхнер (1850—1924) — немецкий химик и изобретатель, усовершенствовавший промышленное производство ультрамарина. Запатентовал придуманную им воронку и колбу;
  • Юлиус Петри (1852—1921) — микробиолог, ассистент немецкого врача Ричарда Коха, открывшего возбудителя туберкулеза. В 1877 году изобрел лабораторную посуду, получившую его имя.

Чаша Петри. Источник: pcgroup.ru

Виды лабораторной посуды по материалам, из которых она изготовлена

Лабораторная посуда изготавливается из материалов, позволяющих работать с активными химическими соединениями таким образом, чтобы не происходило химической реакции между препаратами из эксперимента и компонентами посуды. Кроме того материалы должны быть термоустойчивыми и обладать высокой механической прочностью.

Чаще всего для изготовления лабораторной посуды применяют следующие материалы:

Стеклянная лабораторная посуда обладает рядом преимуществ:

  • высокая степень прозрачности материала;
  • инертность по отношению ко многим химическим препаратам и реактивам;
  • небольшой коэффициент теплового расширения;
  • термоустойчивость;
  • относительно невысокая цена.

При добавлении к стеклу специальных компонентов и дополнительному закаливанию получают материал для лабораторной посуды с улучшенными показателями.

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

  • очень низкая стоимость;
  • возможность использования одноразовой посуды, когда необходимо быстро добиться состояния стерильности;
  • высокая химическая устойчивость — даже к плавиковой кислоте, к которой неустойчиво боросиликатное стекло;
  • хорошие показатели механической прочности;
  • безопасность в работе — в отличие от стеклянной посуды не оставляет осколков.
  • самый главный недостаток — возможность работы в узком диапазоне температур. Посуда из пластика не выдерживает нагревания выше 130°С и охлаждения ниже 35°С;
  • не такая высокая степень прозрачности, как у стекла;
  • неэкологичность — пластик очень медленно разлагается в природе.

В основном в качестве пластика для лабораторной посуды используют полипропилен. Он очень дешевый и легкий, прост в изготовлении и использовании. Из минусов — неустойчив к воздействию сильных кислот.

Фарфоровая лабораторная посуда используется для:

  • перемалывания твердых веществ;
  • проведения химических реакций, где требуется быстрое нагревание.
  • непрозрачность;
  • неустойчивость к механическим повреждениям;
  • относительно высокая стоимость.
  • выдерживает огромные температуры;
  • высокая химическая инертность.

Из какого стекла делают посуду для химических исследований

Ее изготавливают из особых видов стекла, обладающих улучшенными показателями:

  • высокая степень термоустойчивости;
  • небольшой коэффициент теплового расширения;
  • инертность по отношению к химическим веществам;
  • полная прозрачность;
  • механическая прочность;
  • отсутствие сколов и трещин.

Одними из лучших физико-механических и химических характеристик обладает посуда из боросиликатного стекла. Оно обладает высокой химической устойчивостью к воздействию:

  • кислот;
  • щелочей;
  • солей;
  • органических растворителей.

По цене оно намного дешевле кварцевого и поэтому очень часто используется в лабораториях. Его широко применяют при изготовлении:

  • пробирок;
  • колб;
  • чаш;
  • стаканов;
  • пипеток;
  • пластин;
  • наконечников.

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

  • можно нагревать до температуры 1100 градусов по Цельсию (боросиликатное начинает размягчаться уже при 500 градусах);
  • температура плавления доходит до 1500°С;
  • обладает самым низким коэффициентом теплового расширения.
  • цена намного дороже, чем у боросиликатного;
  • высокая хрупкость.

Понимание callback-функций (колбеков)

Callback-функции чрезвычайно важны в языке Javascript. Они есть практически повсюду. Но, несмотря на имеющийся опыт программирования на C/Java, с ними у меня возникли трудности (как и с самой идеей асинхронного программирования), и я решил в этом разобраться. Странно, но я не смог найти в интернете хороших вводных статей о callback-функциях — в основном попадались отрывки документации по функциям call() и apply() или короткие кусочки кода, демонстрирующие их использование, и вот, набив шишек в поисках истины, я решил написать введение в callback-функции самостоятельно.

Функции — это объекты

Чтобы понимать callback-функции, нужно понимать обычные функции. Это может показаться банальностью, но функции в Javascript’е — немного странные штуки.

Функции в Javascript’е — на самом деле объекты. А именно, объекты класса Function , создаваемые конструктором Function . В объекте Function содержится строка с JS-кодом данной функции. Если вы перешли с языка C или Java, это может показаться странным (как код может быть строкой?!), но, вообще говоря, в Javascript’е такое сплошь и рядом. Различие между кодом и данными иногда размывается.

// можно создать функцию, передав в конструктор Function строку с кодом var func_multiply = new Function("arg1", "arg2", "return arg1 * arg2;"); func_multiply(5, 10); // => 50 

Преимущество концепции «функция-как-объект» заключается в том, что код можно передавать в другую функцию точно так же, как обычную переменную или объект (потому что в буквальном понимании код — всего лишь объект).

Передача функции как callback-функции

Передавать функцию в качестве аргумента просто.

// определяем нашу функцию с аргументом callback function some_function(arg1, arg2, callback) < // переменная, генерирующая случайное число в интервале между arg1 и arg2 var my_number = Math.ceil(Math.random() * (arg1 - arg2) + arg2); // теперь всё готово и мы вызываем callback, куда передаём наш результат callback(my_number); >// вызываем функцию some_function(5, 15, function (num) < // эта анонимная функция выполнится после вызова callback-функции console.log("callback called! " + num); >); 

Может показаться глупостью создавать такой перемудрённый код, когда можно вернуть значение нормальным способом, но существуют ситуации, в которых это непрактично и callback-функции необходимы.

Не загромождайте выход

Традиционно функции в ходе выполнения принимают на вход аргументы и возвращают значение, используя выражение return (в идеальном случае единственное выражение return в конце функции: одна точка входа и одна точка выхода). Это имеет смысл. Функции — это, в сущности, маршруты между вводом и выводом.

Javascript даёт возможность делать всё немного по-другому. Вместо того чтобы дожидаться, пока функция закончит выполняться и вернёт значение, мы можем использовать callback-функции, чтобы получить его асинхронно. Это полезно для случаев, когда требуется много времени для завершения, например, при AJAX-запросах, ведь мы не можем приостановить браузер. Мы можем продолжить заниматься другими делами в ожидании вызова колбека. Фактически, очень часто от нас требуется (или, точнее, нам настоятельно рекомендуется) делать всё асинхронно в Javascript’е.

Вот более детальный пример, в котором используется AJAX для загрузки XML-файла и используется функция call() для вызова callback-функции в контексте запрошенного объекта (это значит, что когда мы укажем ключевое слово this внутри callback-функции, оно будет ссылаться на запрошенный объект):

function some_function2(url, callback) < var httpRequest; // создаём наш XMLHttpRequest-объект if (window.XMLHttpRequest) < httpRequest = new XMLHttpRequest(); >else if (window.ActiveXObject) < // для дурацкого Internet Explorer'а httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); >httpRequest.onreadystatechange = function () < // встраиваем функцию проверки статуса нашего запроса // это вызывается при каждом изменении статуса if (httpRequest.readyState === 4 && httpRequest.status === 200) < callback.call(httpRequest.responseXML); // вызываем колбек >>; httpRequest.open('GET', url); httpRequest.send(); > // вызываем функцию some_function2("text.xml", function () < console.log(this); >); console.log("это выполнится до вышеуказанного колбека"); 

В этом примере мы создаём объект httpRequest и загружаем файл XML. Типичная парадигма возвращения значения в конце функции тут больше не работает. Наш запрос обрабатывается асинхронно, а это означает, что мы начинаем запрос и говорим ему вызвать нашу функцию, как только он закончится.

Мы используем здесь две анонимных функции. Важно помнить, что нам бы не составило труда использовать и именованные функции, но во имя лаконичности мы сделали их вложенными. Первая анонимная функция выполняется всякий раз при изменении статуса в нашем объекте httpRequest. Мы игнорируем это до тех пор, пока состояние не будет равно 4 (т.е. запрос выполнен) и статус будет равен 200 (т.е. запрос выполнен успешно). В реальном мире вам бы захотелось проверить, не провален ли запрос, но мы предполагаем, что файл существует и может быть загружен браузером. Эта анонимная функция связана с httpRequest.onreadystatechange, так что она выполняется не сразу, а вызывается каждый раз при изменении состояния в нашем запросе.

Когда мы наконец завершаем наш AJAX-запрос, мы не просто запускаем callback-функцию, мы используем для этого функцию call() . Это ещё один способ вызова callback-функции. Метод, использованный нами до этого — простой запуск функции здесь сработал бы хорошо, но я подумал, что стоит продемонстрировать и использование функции call() . Как вариант, можно использовать функцию apply() (обсуждение разницы между ней и call() выходят за рамки этой статьи, скажу лишь, что это затрагивает способ передачи аргументов функции).

В использовании call() замечательно то, что мы сами устанавливаем контекст, в котором выполняется функция. Это означает, что когда мы используем ключевое слово this внутри нашей callback-функции, оно ссылается на то, что мы передаём первым аргументом в call() . В данном примере, когда мы ссылались на this внутри нашей анонимной функции, мы ссылались на responseXML, полученный в результате AJAX-запроса.

Наконец, второе выражение console.log выполнится первым, потому что callback-функция не выполняется до тех пор, пока не закончен запрос, и пока это произойдёт, последующие части кода продолжают спокойно выполняться.

Обёртывай это

Надеюсь, теперь вы стали понимать callback-функции достаточно хорошо, чтобы начать их использовать в своём собственном коде. Мне всё ещё трудно структурировать код, который зиждется на callback-функциях (в конце концов он становится похож на спагетти… мой разум слишком привык к обычному структурному программированию), но они — очень мощный инструмент и одна из интереснейших частей языка Javascript.

Делегаты и колбэки в Swift простым языком. Что же такое этот delegate, и как работает callback

В Swift при изучении UI (User Interface) каждый рано или поздно приходит к необходимости использования делегата. Все гайды о них пишут, и вроде бы делаешь, как там написано, и вроде бы работает, но почему и как это работает, не у каждого в голове укладывается до конца. Лично у меня даже какое-то время складывалось ощущение, что delegate – это какое-то волшебное слово, и что оно прям встроено в язык программирования (вот, насколько запутаны были мои мысли от этих гайдов). Давайте попытаемся объяснить простым языком, что же это такое. А разобравшись с делегатом, уже гораздо легче будет понять, что такое колбэк (callback), и как работает он.

Официант и повар

Итак, перед тем как перейти к коду давайте представим себе некоего официанта и какого-нибудь повара. Официант получил заказ от клиента за столиком, но сам он готовить не умеет, и ему нужно попросить об этом повара. Он может пойти на кухню и сказать повару: «Приготовь курицу». У повара есть соответствующие инструменты (сковорода, масло, огонь…) и навык приготовления. Повар готовит и отдает блюдо официанту. Официант берет то, что сделано поваром и несет к клиенту.

А теперь представим себе ситуацию, что официант не может прибежать на кухню и сказать повару напрямую, какое блюдо у него заказали. Не пускают его на кухню (допустим, такие правила) или кухня находится на другом этаже (устанешь бегать). И единственный способ общения – это окошко мини-лифта. Официант кладет туда записку, нажимает кнопку, лифт уехал на кухню. Приезжает обратно с готовым блюдом. Запомнили? Теперь зафиксируем ситуацию в голове, попробуем воссоздать через код и понять, как это связано с нашей темой.

Перенесем в код

Создаем классы официанта и повара. Для простоты сделаем это в плейграунде:

import UIKit // Создаем класс официанта class Waiter < /// Свойство "заказ" - опциональная информация о текущем заказе. О заказе может узнать только официант, поэтому "private". private var order: String? /// Метод "принять заказ". func takeOrder(_ food: String) < print("What would you like?") print("Yes, of course!") order = food sendOrderToCook() >/// Метод "отправить заказ повару". Мог бы сделать только официант. Но как? private func sendOrderToCook() < // . Как передать повару заказ? >/// Метод "доставить блюдо клиенту". Умеет только официант. private func serveFood() < print("Your \(order!). Enjoy your meal!") >> // Создаем класс повара class Cook < /// Свойство "сковорода". Есть только у повара. private let pan: Int = 1 /// Свойство "плита". Есть только у повара. private let stove: Int = 1 /// Метод "приготовить". Умеет только повар. private func cookFood(_ food: String) ->Bool < print("Let's take a pan") print("Let's put \(food) on the pan") print("Let's put the pan on the stove") print("Wait a few minutes") print("\(food) is ready!") return true >>

Теперь создаем их экземпляры (нанимаем на работу), и просим официанта получить заказ (курицу):

// Нанимаем на работу официанта и повара (создаем экземпляры): let waiter = Waiter() let cook = Cook() // Сначала скажем официанту получить заказ. Допустим, он получает курицу: waiter.takeOrder("Chiken")

Как теперь официанту передать повару, что ему приготовить?

Конечно, можно было бы написать ниже вот так, если бы свойства и методы официанта и повара не были private. Но так как у них уровень доступа private, то это не сработает:

cook.cookFood(waiter.order!) // 'cookFood' is inaccessible due to 'private' protection level // 'order' is inaccessible due to 'private' protection level

И к тому же мы использовали некий сторонний код «снаружи» классов официанта и повара, которому необходимо иметь доступ к private свойствам и методам этих классов. А как официанту передать «изнутри» себя, используя встроенные свойства и методы своего класса? Тот же вопрос со стороны повара: «Как ему приготовить то, что известно только официанту, используя свойства и методы своего класса?»

Тут на помощь приходит «лифт». В этот лифт официант кладет записку с заказом. А повар берет записку из лифта и ставит в лифт готовое блюдо для передачи повару. Такой «лифт» реализуется через протокол «Взаимообмен через лифт»:

protocol InterchangeViaElevatorProtocol < func cookOrder(order: String) ->Bool >

В данном случае мы говорим, что у лифта есть «интерфейс», который должен быть понятен и официанту, и повару. То есть правила взаимообмена через этот лифт. Правила взаимообмена должны знать и официант, и повар. Они простые: официант кладет записку, а повар готовит по ней.

Теперь давайте поправим классы, чтобы официант мог общаться с поваром через этот лифт. Научим их работать по этому правилу(протоколу).

Подпишем класс повара под протокол лифта. Грубо говоря, мы научим всех наших поваров соблюдать правила, описанные в этом протоколе «Обмен через лифт». В таком случае Xcode заставит нас дописать в класс повара метод из протокола. Этот метод в данном примере должен будет вернуть Bool значение.

В этом методе мы вызовем ранее созданный метод cookFood, который повар умеет выполнять.

extension Cook: InterchangeViaElevatorProtocol < func cookOrder(order: String) ->Bool < cookFood(order) >>

Далее официанту добавим свойство «получатель заказа через лифт». Официант знает, что этот получатель знает правила и приготовит то, что в записке.

extension Waiter < var receiverOfOrderViaElevator: InterchangeViaElevatorProtocol? < return cook >>

В данном примере мы использовали расширение, которое не позволяет делать переменные с хранимыми свойствами. Поэтому мы вынуждены дописать в фигурных скобках return cook.

Но можно сделать по-другому: просто добавить без расширения прямо внутрь класса официанта это опциональное свойство, а затем извне этому свойству присвоить экземпляр нашего повара. Главное не забыть подписать класс повара под протокол.

Давайте так и сделаем, чтобы не усложнять наш простой пример экстеншенами. Удалим эти экстешнены и просто добавим строчки в ранее созданные классы, и подпишем класс повара под протокол.

Вот теперь как будут выглядеть наши классы:

import UIKit protocol InterchangeViaElevatorProtocol < func cookOrder(order: String) ->Bool > class Waiter < // Далее официанту добаим свойство "получатель заказа через лифт". Официанту известно, что этот получатель знает правила и приготовит то, что в записке. var receiverOfOrderViaElevator: InterchangeViaElevatorProtocol? var order: String? func takeOrder(_ food: String) < print("What would you like?") print("Yes, of course!") order = food sendOrderToCook() >private func sendOrderToCook() < // . Как передать повару заказ? >private func serveFood() < print("Your \(order!). Enjoy your meal!") >> // Создаем класс повара class Cook: InterchangeViaElevatorProtocol < private let pan: Int = 1 private let stove: Int = 1 private func cookFood(_ food: String) ->Bool < print("Let's take a pan") print("Let's put \(food) on the pan") print("Let's put the pan on the stove") print("Wait a few minutes") print("\(food) is ready!") return true >// Необходимый метод, согласно правилу(протоколу): func cookOrder(order: String) -> Bool < cookFood(order) >>

В классе официанта убрали пока private у свойства order (нужно сейчас для наглядности).

Далее все по той же схеме:

  1. Нанимаем официанта и повара
  2. Добавим официанту заказ:
// Нанимаем на работу официанта и повара: let waiter = Waiter() let cook = Cook() // Добавим официанту заказ: waiter.takeOrder("Chiken")

Теперь скажем официанту, что его «получатель заказа через лифт» – это наш повар.

// Теперь скажем официанту, что его "получатель заказа через лифт" - это наш повар: waiter.receiverOfOrderViaElevator = cook

Как уже говорилось ранее, официант знает, что этот получатель знает правила и приготовит то, что в записке.

Теперь официант может нашего «получателя заказа через лифт» попросить приготовить заказ:

// Теперь официант может нашего "получателя заказа через лифт" попросить приготовить заказ: waiter.receiverOfOrderViaElevator?.cookOrder(order: waiter.order!)

Запускаем код, получаем результат!

/* What would you like? Yes, of course! Let's take a pan Let's put Chiken on the pan Let's put the pan on the stove Wait a few minutes Chiken is ready! */

Как Дубровский «имел связь с Машей через дупло», так и наш официант теперь имеет возможность отправлять заказы повару через протокол и известный официанту метод данного протокола.

Можно теперь доделать у класса «Официант» метод передачи заказа, чтобы официант мог делать это «изнутри себя», то есть используя свои собственные свойства и методы, а не указания со стороны.

 private func sendOrderToCook() < //Добавим вызов метода cookOrder у нашего "получателя заказов через лифт": receiverOfOrderViaElevator?.cookOrder(order: order!) >

Вот и все дела! В данном случае мы добавляли официанту опциональное свойство receiverOfOrderViaElevator, подписанное под протокол. Это свойство и есть делегат. Можете заменить название этого свойства на delegate, если хотите. По сути ничего не изменится, просто это более универсальное слово, вот и все.

Теперь вы понимаете принцип работы делегата? «Окей, – скажете вы. – А как это использовать в UI?»

Как использовать delegate при создании контроллеров в UI?

В UI с необходимостью использования делегата чаще всего встречаются в случае, когда необходимо от одного «дочернего» контроллера передать информацию «родительскому». Например, нужно передать от ячейки информацию создавшему ее table view или collection view. От table view или collection view передать информацию ячейке легко: это можно сделать при ее инициализации. А вот обратно передать информацию сама ячейка напрямую не может. Вот тут и спасает шаблон (паттерн) под названием «Делегат» («Delegate»).

Кстати, слово Delegable в русской раскладке будет как «Вудупфиду». Так вот, значит, о чем пела Мерлин Монро!

Давайте представим, что повар – это хозяин кафе. И он нанимает нашего официанта. То есть создает экземпляр класса Waiter. Добавим ему умение(метод) hireWaiter. Получим вот такой класс (кстати, пусть на этот раз это будет шеф-повар):

// Создаем класс шеф-повара class Chief: InterchangeViaElevatorProtocol < private let pan: Int = 1 private let stove: Int = 1 private func cookFood(_ food: String) ->Bool < print("Let's take a pan") print("Let's put \(food) on the pan") print("Let's put the pan on the stove") print("Wait a few minutes") print("\(food) is ready!") return true >// Необходимый метод, согласно правилу(протоколу): func cookOrder(order: String) -> Bool < cookFood(order) >// Шеф-повар умеет нанимать официантов в свое кафе: func hireWaiter() -> Waiter < return Waiter() >>

Теперь шеф-повар открывает кафе и нанимает официанта (создаем экземпляр шеф-повара и вызываем у него метод hireWaiter):

// Создаем экземпляр шеф-повара (шеф-повар открывает кафе): let chief = Chief() // Шев-повар нанимает официанта: let waiter = chief.hireWaiter() // Добавим официанту заказ: waiter.takeOrder("Chiken")

Далее все по старинке. Нужно обучить официанта, что его «получатель заказа через лифт» – это наш шеф-повар. И тогда он сможет передать ему заказ.

// Обучаем официанта, что его "получатель заказа через лифт" - это наш шеф-повар: waiter.receiverOfOrderViaElevator = chief // Теперь официант может нашего "получателя заказа через лифт" попросить приготовить заказ: waiter.receiverOfOrderViaElevator?.cookOrder(order: waiter.order!)

Если запустить код, то снова все сработает.

Отлично. А теперь представим, что появился новый шеф-повар, который рассказывает официанту ещё при найме на работу, что его «получателем заказа через лифт» будет сам шеф-повар.

class SmartChief: Chief < override func hireWaiter() ->Waiter < let waiter = Waiter() waiter.receiverOfOrderViaElevator = self // Сразу же настраивает официанту свойство получателя заказа через лифт return waiter >>

Здесь мы просто наследовали класс SmartChief от класса Chief и переписали метод найма официантов.

Получается, что теперь нет необходимости как-то отдельно указывать официанту (обучать), кто его получатель заказа через лифт. Он с самого начала работы уже об этом знает!

let smartChief = SmartChief() let smartWaiter = smartChief.hireWaiter() smartWaiter.takeOrder("Fish") /* What would you like? Yes, of course we have Fish! Let's take a pan Let's put Fish on the pan Let's put the pan on the stove Wait a few minutes Fish is ready! */

Тоже самое и в контроллерах:

  1. Пишем протокол (правило), в котором описываем нужный нам метод, который принимает необходимые аргументы и, если нужно, что-то выдает.
  2. Подписываем «порождающий» контроллер под этот протокол и пишем в нем этот метод.
  3. У дочернего контроллера (например, у ячейки) добавляем опциональное свойство делегата, являющееся типом нашего протокола (то есть поддерживающего тип нашего протокола)
  4. При создании дочернего контроллера ставим в его свойстве делегата себя, то есть self «порождающего» контроллера.

Естественно, это можно делать не только с «порождающими» контроллерами, а вообще с любыми объектами, которые мы хотим научить общаться друг с другом.

На этом про делегаты всё. Надеюсь, было полезно! Теперь разберемся в колбэках.

Колбэки (колбеки, callback). Это тот же делегат? Ну, почти

Итак, мы выяснили, что делегаты позволяют одним объектам «общаться» с другими. Иначе говоря, позволяют одним объектам добиваться своей цели с помощью свойств и методов других объектов. Для чего же нужны колбэки? И почему они в одной статье с делегатами?

Колбэк (callback) – это тоже шаблон программирования, как и делегат. С его помощью также одни объекты могут добиваться своих целей с помощью свойств и методов других объектов. Только делать они это будут сами.

Ленивый шеф-повар, талантливый официант

Представьте себе, что в другом ресторане шеф-повар очень ленивый (или усталый, или заболел). Официант принял заказ, звонит повару, а тот ему говорит: «Давай-ка сам приготовь! Возьми мою сковородку, поставь на плиту и приготовь по рецепту!» Наш официант оказался не из робкого десятка, берет инструкцию, инструменты повара и все делает сам. Это и есть подход через колбэк.

Давайте посмотрим это на практике.

Создадим класс талантливого официанта. Добавим опциональное свойство функционального типа. Под этим названием кроется функция, которая принимает на вход аргумент с типом String и возвращает результат с типом Bool. Прямо как метод cookFood у нашего повара! Это что-то вроде способности сделать что-то по инструкции.

/// Класс талантливого официанта class TalentedWaiter < var order: String? // Добавим опциональное свойство функционального типа. Это функция, которая принимает на вход аргумент с типом String и возвращает результат с типом Bool. var doEverything: ((String) ->Bool)? func takeOrder(_ food: String) < print("What would you like?") print("Yes, of course we have \(food)!") order = food // Вместо передачи заказа шев-повару официант попытается сделать сам: doOwnself() >private func doOwnself() -> Bool < // Если инструкция существует, то он ее выполнит: if let doEverything = doEverything < let doOwnself = doEverything(order!) return doOwnself >else < return false >> >

Далее создаем класс ленивого шеф-повара. В этот раз при найме на работу талантливого официанта, повар не назначает себя делегатом, а обучает его самому готовить. Он передает в именованное функциональное свойство официанта свое умение готовить, которое включает в себя и доступ к сковородке с плитой. То есть он присваивает замыкание его свойству, и в этом замыкании передает свой собственный метод:

// Создаем класс ленивого шеф-повара class LazyChief < private let pan: Int = 1 private let stove: Int = 1 private func cookFood(_ food: String) ->Bool < print("I have \(pan) pan") print("Let's put \(food) on the pan!") print("I have \(stove) stove. Let's put the pan on the stove!") print("Wait a few minutes. ") print("\(food) is ready!") return true >// Умение нанимать талантливых официантов: func hireWaiter() -> TalentedWaiter < let talentedWaiter = TalentedWaiter() // Повар учит официанта готовить самому. Он передает ему инструкцию в виде замыкания, в котором прописывает свой собственный метод cookFood: talentedWaiter.doEverything = < order in self.cookFood(order) >return talentedWaiter > >

В результате после появления такого шеф-повара, найме на работу официанта, официант готовит блюдо самостоятельно, как только примет заказ:

let lazyChief = LazyChief() let talentedWaiter = lazyChief.hireWaiter() talentedWaiter.takeOrder("Meat") /* What would you like? Yes, of course we have Meat! I have 1 pan Let's put Meat on the pan! I have 1 stove. Let's put the pan on the stove! Wait a few minutes. Meat is ready! */

Таким образом, как и в случае с делегатом, официант «добился» своей цели и приготовил заказ.

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

Однако у этого способа есть один минус – создание сильных связей. Поэтому нужно всегда помнить, что self нужно передавать через слабую ссылку, иначе экземпляр шеф-повара навсегда свяжется с экземпляром официанта, что приведет к утечке памяти даже после удаления этих объектов.

Поэтому последний штрих будет добавить [weak self] перед in и аргументами в передающем замыкании. Всегда помните об этом, пожалуйста!

talentedWaiter.doEverything =

На этом у меня все. Надеюсь, вам было полезно. Успехов в изучении!

Скачать итоговый код можно на GitHub

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *