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

321
Chris 22 Янв 2009 в 02:52
4
См. Hooking @ Wikipedia. Ссылка скрыта в одном из ответов с меньшим количеством голосов.
 – 
Palec
5 Июл 2014 в 22:25
События и хуки похожи. Так есть ли разница? Если обратные вызовы событий вызываются только после того, как событие происходит (например, click), существует событие onbeforeunload. Похоже, что обратный вызов будет вызван перед фактическим событием. Так технически это событие замаскировано за крючок? Вызываются ли обработчики ловушек до, вместо или после основной операции? ... Я считаю, что между крючком и событием есть несколько отличий. Хук выглядит как низкоуровневое вмешательство, а событие похоже на ограниченную версию ловушки. Почему об этом никто не говорит? Кто-то просветит нас.
 – 
akinuri
25 Апр 2021 в 15:39

13 ответов

Лучший ответ

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

172
Micah 22 Янв 2009 в 02:55
12
Это похоже на обратный вызов?
 – 
Chris
22 Янв 2009 в 03:05
27
Хуки часто (но не всегда) используют функции обратного вызова. Например, вы можете подключить систему событий с помощью «hookEvent (Events.STARTUP, myCallbackFunction)». Вы передаете указатель на функцию функции hookEvent, поэтому она знает, какую функцию вызывать при возникновении события. Надеюсь, это поможет :-)
 – 
William Brendel
22 Янв 2009 в 03:12
8
Точно. Обратный вызов - это «тип» ловушки.
 – 
Micah
22 Янв 2009 в 04:33
25
Эм ... нет. Обратный вызов - это обратный вызов и не имеет ничего общего с хуками, обратные вызовы просто ИСПОЛЬЗУЮТСЯ для РЕАЛИЗАЦИИ ловушек-методов. Обратные вызовы - это указатели (RELJMP) на функции / методы / процедуры (CALL), хуки - это модификации запущенных приложений.
 – 
specializt
27 Окт 2014 в 17:31
1
Нет. Прерывание вызывает выполнение инструкций в определенном месте (прерывание). Однако вы можете подключиться к процессу обработки прерывания, например, изменив таблицу, в которой перечислены местоположения обработчиков прерываний, чтобы ваш код вызывал сначала при прерывании (а затем ваш код вызывал ранее присутствующий код обработки прерывания, в метод гирляндной цепи)
 – 
David Tonhofer
16 Дек 2016 в 04:51

Много ответов, но нет примеров, поэтому добавляем фиктивный: следующий complicated_func предлагает два крючка для изменения его поведения

from typing import List, Callable


def complicated_func(
    lst: List[int], hook_modify_element: Callable[[int], int], hook_if_negative=None
) -> int:
    res = sum(hook_modify_element(x) for x in lst)
    if res < 0 and hook_if_negative is not None:
        print("Returning negative hook")
        return hook_if_negative
    return res


def my_hook_func(x: int) -> int:
    return x * 2


if __name__ == "__main__":
    res = complicated_func(
        lst=[1, 2, -10, 4],
        hook_modify_element=my_hook_func,
        hook_if_negative=0,
    )
    print(res)
0
gebbissimo 28 Май 2021 в 12:59

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

В былые времена, когда компьютеры были по-настоящему личными, а вирусы были менее распространены (я говорю о 80-х), для вызова вашего кода было достаточно просто установить патч для самого программного обеспечения операционной системы. Я помню, как писал расширение для языка Applesoft BASIC на Apple II, которое просто подключало мой код к интерпретатору BASIC, вводя вызов моего кода до того, как какая-либо строка была обработана.

На некоторых компьютерах были заранее спроектированные перехватчики, одним из примеров которых является поток ввода-вывода на Apple II. Он использовал такой крючок для внедрения всей дисковой подсистемы (ПЗУ Apple II изначально создавались в те дни, когда кассеты были основным носителем информации для ПК). Вы управляли дисками с помощью печати кода ASCII 4 (CTRL-D), за которым следовала команда, которую вы хотели выполнить, затем CR, и она была перехвачена дисковой подсистемой , который подключился к процедурам печати Apple ROM.

Так, например, строки:

PRINT CHR(4);"CATALOG"
PRINT CHR(4);"IN#6"

Отобразит содержимое диска, а затем повторно инициализирует машину. Это позволяло использовать такие уловки, как защита ваших программ BASIC, задав в первой строке следующую строку:

123 REM XIN#6

Затем с помощью POKE вставить символ CTRL-D вместо X. Затем любой, кто попытается перечислить ваш источник, отправит последовательность повторной инициализации через процедуры вывода, где дисковая подсистема обнаружит ее.

Часто нам приходилось прибегать к подобным уловкам, чтобы добиться желаемого поведения.

В настоящее время, когда операционная система более безопасна, она сама предоставляет средства для перехвата, поскольку вам больше не нужно изменять операционную систему «в полете» или на диске.

Они существуют уже давно . Они были у мэйнфреймов (называемые выходами), и даже сейчас многие программы для мэйнфреймов используют эти возможности. Например, бесплатная система управления исходным кодом, поставляемая с z / OS (называемая SCLM), позволяет полностью заменить подсистему безопасности, просто поместив свой собственный код в выход.

90
paxdiablo 9 Дек 2009 в 02:47

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

Например, Drupal CMS предоставляет разработчикам ловушки, позволяющие им выполнять дополнительные действия после создания «узла содержимого». Если разработчик не реализует ловушку, узел создается обычным образом. Если разработчик реализует ловушку, он может запускать дополнительный код при создании узла. Этот код может делать что угодно, включая откат и / или изменение исходного действия. Он также может делать что-то совершенно не связанное с созданием узла.

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

Другой пример. Иногда веб-разработчики называют имена классов и / или идентификаторы элементов хуками. Это потому, что, поместив идентификатор / имя класса в элемент, они могут затем использовать Javascript для изменения этого элемента или «подключиться» к документу страницы. (это растягивает значение, но оно широко используется и заслуживает упоминания)

53
Alan Storm 22 Янв 2009 в 03:18
Что вы подразумеваете под «подключением к странице документа»? Не могли бы вы привести пример? Я понял первый пример - присвоение html-элементу идентификатора, чтобы вы могли использовать javacript для изменения элемента.
 – 
committedandroider
26 Сен 2018 в 18:46

Просто сказал:

Хук - это средство выполнения пользовательского кода (функции) до, после или вместо существующего кода. Например, может быть написана функция для «подключения» к процессу входа в систему для выполнения функции Captcha перед продолжением обычного процесса входа в систему.

38
Joseph Vernice 2 Авг 2016 в 17:36

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

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

Распространенный метод реализации - предоставить функции пустой список обратных вызовов, а затем предоставить возможность расширения списка обратных вызовов. Базовый код всегда будет вызывать функцию в одно и то же время, но с пустым списком обратных вызовов функция ничего не делает. Это сделано намеренно.

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

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

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

23
Jack Stout 20 Июл 2017 в 04:04

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

17
geowa4 22 Янв 2009 в 02:58

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

4
urgent 5 Апр 2014 в 09:05

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

2
dusoft 22 Янв 2009 в 03:00

Цепочка хуков - это набор функций, в которых каждая функция вызывает следующую. Что важно в цепочке перехватчиков, так это то, что программист может добавить в цепочку еще одну функцию во время выполнения. Один из способов сделать это - найти известное место, где хранится адрес первой функции в цепочке. Затем вы сохраняете значение этого указателя на функцию и перезаписываете значение по начальному адресу адресом функции, которую хотите вставить в цепочку ловушек. Затем функция вызывается, выполняет свое дело и вызывает следующую функцию в цепочке (если вы не решите иначе). Естественно, существует ряд других способов создания цепочки перехватчиков, от записи непосредственно в память до использования средств метапрограммирования таких языков, как Ruby или Python.

Примером цепочки перехватчиков является способ обработки сообщений приложением MS Windows. Каждая функция в цепочке обработки либо обрабатывает сообщение, либо отправляет его следующей функции в цепочке.

1
Joe Soul-bringer 22 Янв 2009 в 03:24

В системе управления контентом Drupal «крючок» имеет относительно конкретное значение. Когда происходит внутреннее событие (например, создание контента или вход пользователя), модули могут реагировать на событие, реализуя специальную функцию «ловушки». Это делается с помощью соглашения об именах - [your-plugin-name] _user_login (), например, для события User Login.

Из-за этого соглашения базовые события называются «хуками» и появляются с такими именами, как «hook_user_login» и «hook_user_authenticate ()» в документации API Drupal.

1
Eaton 22 Янв 2009 в 03:35
Это соответствует упомянутой выше идее «обратного вызова», «чтобы реагировать, когда что-то происходит». В этом случае обратный вызов не регистрируется явно, а основан на «магическом именовании». В настоящее время это обсуждается на drupal.org, см. Использование Symfony EventDispatcher для обработчиков событий
 – 
donquixote
24 Май 2012 в 11:39
В общем, перехватчик / обратный вызов / слушатель может быть «известен вызывающему коду» различными способами (не говоря уже о том, что это завершено): 1. Функции с волшебным именем 2. Классы с волшебным именем 3. Явно зарегистрированные функции 4. Явно зарегистрированные объекты (слушатели, подписчики, наблюдатели) 5. Явно зарегистрированные имена классов (+ необязательные аргументы конструктора), которые будут созданы до срабатывания ловушки. 6. путем изменения телефонного кода
 – 
donquixote
24 Май 2012 в 11:39

Короче говоря, вы можете изменить код вызова API, например MessageBox, чтобы он выполнял другую функцию, отредактированную вами (глобально будет работать в масштабе всей системы, локально будет работать в масштабе всего процесса).

1
Marko 3 Окт 2012 в 20:53

Часто перехват относится к перехвату сообщений Win32 или эквивалентам Linux / OSX, но в более общем смысле перехватчик - это просто уведомление другого объекта / окна / программы / и т. д. о том, что вы хотите получать уведомления, когда происходит указанное действие. Например: все окна в системе уведомляют вас о своем закрытии.

Как правило, перехват в некоторой степени опасен, поскольку выполнение его без понимания того, как оно влияет на систему, может привести к нестабильности или, как минимум, к неожиданному поведению. Он также может быть ОЧЕНЬ полезным при определенных обстоятельствах, подумал я. Например: FRAPS использует его, чтобы определить, в каких окнах должен отображаться счетчик FPS.

1
Toji 22 Янв 2009 в 03:05