首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当消息不被理解时,法老是如何启动调试器的?

当消息不被理解时,法老是如何启动调试器的?
EN

Stack Overflow用户
提问于 2019-02-02 19:42:54
回答 2查看 212关注 0票数 5

启动发送未实现消息的代码时,法罗将启动调试器。

据我所知,它通过Object >> doesNotUnderstand工作,这会触发异常,这将导致调试器窗口。

问题是,Object >> doesNotUnderstand到底是做什么的,这与其他交互助手有什么不同,比如从不存在变量开始的交互帮助?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-02-02 20:36:44

调试器是作为对未处理异常的响应打开的。为了更好地解释,我们可以从触发系统中任何地方都没有捕获的异常开始。例如,我们可以在游乐场Error signal: 'an error'.中执行(信号在法老中抛出一个错误)。这将打开以下调试器:

当异常发生时,系统首先尝试为该异常查找异常处理程序。如果没有找到异常处理程序,则系统将消息defaultAction发送到异常。这在类Error中实现为:

代码语言:javascript
复制
Error>>#defaultAction
    "No one has handled this error, but now give them a chance to decide how 
    to debug it.  If none handle this either then open debugger 
    (see UnhandedError-defaultAction)"

    UnhandledError signalForException: self

因此,系统通过抛出另一个异常UnhandledError来响应未处理的异常。同样,如果没有为新异常找到异常处理程序,则系统将消息defaultAction发送到异常对象。在本例中,异常是UnhandledError的一个实例,该类重写器defaultAction具有以下实现:

代码语言:javascript
复制
UnhandledError>>#defaultAction
    <reflective: #unhandledErrorDefaultAction:message:>
    ^ UIManager default unhandledErrorDefaultAction: self exception

方法unhandledErrorDefaultAction:非常简单,只发送异常对象消息debug

代码语言:javascript
复制
MorphicUIManager>>#unhandledErrorDefaultAction: anException
    anException debug

方法调试是在Exception中实现的,这是法老中所有异常的根类,如下:

代码语言:javascript
复制
Exception>>#debug
    "open a debugger on myself"
    Processor activeProcess 
        debug: self signalerContext
        title: self description

这就是打开调试器的原因。

在向对象发送未知消息的情况下,MessageNotUnderstood类型的异常将由Object>>#doesNotUnderstand:方法引发。此异常遵循与前面相同的链,系统最终将debug消息发送给打开调试器的MessageNotUnderstood异常。

因此,简而言之:

  • 当未知消息被发送到对象时,系统向对象发送消息#doesNotUnderstand:
  • doesNotUnderstand:引发MessageNotUnderstood类型的异常;
  • 如果未捕获此异常,则引发另一个类型为UnhandledError的异常;
  • 如果没有捕捉到这个新的UnhandledError,它会要求UI管理器处理这种情况;
  • UI管理器将消息debug发送到初始异常,在这种情况下,MessageNotUnderstood异常(只有MorphicUIManager执行此操作;其他UI管理器(如CommandLineUIManager )执行其他操作,如现有图像);
  • debug消息打开调试器。

不存在变量的处理程序在实际编译器中有一个完全不同的实现。当代码在具有未知变量的类中编译时,编译器会检测到这一点,并询问用户该做什么:创建一个新的实例变量或一个本地参数。

如果您试图执行包含未知类的代码,比如UnnknowsClass new.,编译器也会检测到这一点,并询问用户该做什么。在这种情况下也没有例外情况。

还有其他帮助程序使用与doesNotUnderstand:相同的机制,例如引发通知。如果执行Object new notify: 'a notification',则notify:方法将抛出一个Warning异常,该异常将最终打开调试器。

票数 7
EN

Stack Overflow用户

发布于 2019-02-03 02:51:52

为了补充Adrei给出的出色答案,让我补充一下,消息#doesNotUnderstad:与其他消息有点不同。

每次发送消息时,运行时(通常在虚拟机中)会找到与所发送消息的选择器对应的方法。

它通过观察接收者的行为来做到这一点。如果找不到任何方法,则会转到继承的行为(通常是超类中定义的方法),然后继续这种方式,直到找到方法或继承链耗尽为止。这种搜索称为方法查找。

在第二种情况下(当在对象的行为层次结构中不存在方法时),Runtime (1)通过创建一个没有找到选择器的Message对象来重新表示消息,而实际的参数(如果有的话)和(2)会向接收方发送一条带有选择器#doesNotUnderstand:的新消息,并对消息进行参数化。

查找过程会重复,而且(很可能)这一次为接收方找到了选择器#doesNotUnderstand: (它可以实现自己的版本,也可以从类层次结构的顶部继承它)。此时,Adrei描述的步骤如下。

如果接收方出于任何原因不理解#doesNotUnderstand: (双关意),则运行时不能继续并关闭系统(它还能做什么?)

还请注意,如果消息被发送到super,则查找会有一点不同。但这是另一个故事和基本思想。这个问题仍然存在。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54496857

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档