Answers:
本质上,它是代码中的一个地方,允许您使用模块来提供不同的行为或在发生某些事情时做出反应。
挂钩是软件提供的功能,该软件的用户可以在某些情况下调用自己的代码。该代码可以扩充或替换当前代码。
在过去计算机是真正的个人且病毒不那么流行(我说的是80年代)的日子里,这就像修补操作系统软件本身来调用代码一样简单。我记得在Apple II上编写了对Applesoft BASIC语言的扩展,该扩展只是通过在处理任何一行之前向我的代码注入调用,从而将我的代码挂接到BASIC解释器中。
一些计算机具有预先设计的挂钩,例如Apple II上的I / O流。它使用这样的钩子注入整个磁盘子系统(Apple II ROM最初是在盒式磁带作为PC的主要存储介质的年代构建的)。您通过打印 ASCII码4(CTRL-D
),然后打印要执行的命令,然后打印a来控制磁盘,CR
磁盘子系统将其拦截,该磁盘子系统已将自身连接到Apple ROM打印例程中。
因此,例如,这些行:
PRINT CHR(4);"CATALOG"
PRINT CHR(4);"IN#6"
将列出磁盘内容,然后重新初始化计算机。这样可以通过将第一行设置为以下方式来保护您的BASIC程序:
123 REM XIN#6
然后POKE
用于将CTRL-D
字符插入到X
was 所在的位置。然后,任何试图列出您的源的人都将通过磁盘磁盘子系统检测到它的输出例程发送重新初始化序列。
为了获得我们想要的行为,这通常是我们必须采取的手段。
如今,随着操作系统更加安全,它不再需要在运行中或磁盘上修改操作系统,而是为钩子本身提供了便利。
他们已经存在了很长时间。大型机拥有它们(称为出口),并且即使现在,大量的大型机软件仍使用这些功能。例如,z / OS附带的免费源代码控制系统(称为SCLM)使您可以通过简单地将自己的代码放在出口中来完全替换安全子系统。
从广义上讲,“钩子”是一种使您(程序员)能够查看和/或与之交互和/或更改系统/程序中已在进行的事物的事物。
例如,Drupal CMS为开发人员提供了挂钩,让他们在创建“内容节点”之后采取其他措施。如果开发人员未实现挂钩,则按常规创建节点。如果开发人员实现了挂钩,则每当创建节点时,他们都可以运行一些其他代码。该代码可以执行任何操作,包括回滚和/或更改原始操作。它也可以做一些与节点创建完全无关的事情。
回调可以被认为是一种特殊的钩子。通过在系统中实现回调功能,该系统使您可以在操作完成后调用一些其他代码。但是,挂钩(作为通用术语)并不限于回调。
另一个例子。有时,Web开发人员会将元素上的类名称和/或ID称为钩子。那是因为通过将ID /类名称放在元素上,他们可以使用Javascript修改该元素,或“钩入”页面文档。(这是在延伸含义,但它是常用的,值得一提)
挂钩是允许基本代码调用扩展代码的功能类别。这在核心开发人员希望提供可扩展性而不暴露其代码的情况下很有用。
挂钩的一种用法是在视频游戏模块开发中。游戏可能不允许mod开发人员扩展基本功能,但是核心mod库开发人员可以添加挂钩。使用这些挂钩,独立开发人员可以在任何所需事件(例如游戏加载,清单更新,实体交互等)下调用其自定义代码。
一种常见的实现方法是为函数提供一个空的回调列表,然后提供扩展回调列表的功能。基本代码将始终在相同且适当的时间调用该函数,但是对于空的回调列表,该函数不执行任何操作。这是设计使然。
这样,第三方就有机会编写其他代码并将其新的回调添加到挂钩的回调列表中。除了参考可用的挂钩以外,它们还具有扩展功能,对基本系统的风险最小。
钩子不允许开发人员执行其他结构和接口无法完成的任何事情。选择它们时要考虑任务和用户(第三方开发人员)。
为了澄清起见:挂钩允许扩展,可以使用回调实现。回调通常只不过是一个函数指针。计算的函数地址。其他答案/评论中似乎有些混乱。
在Drupal内容管理系统中,“挂钩”具有相对特定的含义。当发生内部事件时(例如,内容创建或用户登录),模块可以通过实现特殊的“挂钩”功能来响应事件。这是通过命名约定完成的-例如,针对用户登录事件的[your-plugin-name] _user_login()。
由于这种约定,在Drupal的API文档中,基础事件被称为“挂钩”,并以“ hook_user_login”和“ hook_user_authenticate()”之类的名称出现。