Как Pharo запускает отладчик, когда сообщение не понято? - PullRequest
0 голосов
/ 02 февраля 2019

Когда вы запускаете отправку кода не реализованного сообщения, Pharo запускает отладчик.

Насколько я понимаю, он работает через Object >> doesNotUnderstand, что вызывает исключение, и это приводит к окну отладчика.

enter image description here

Вопрос в том, что именно делает Object >> doesNotUnderstand, и чем он отличается от других интерактивных помощников, например, начинающих с несуществующей переменной?

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

Просто в дополнение к прекрасному ответу, данному Адреем Чисом, позвольте мне добавить, что сообщение #doesNotUnderstad: немного отличается от других сообщений.

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

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

Во втором случае (когда в иерархии поведения объекта нет метода) Runtime (1) повторно формирует сообщение, создавая Message объект с селектором не найден, а фактические аргументы (если есть) и (2) отправляют получателю новое сообщение с селектором #doesNotUnderstand: и аргументом только что исправленного сообщения.

Процесс поиска повторяется, и (скорее всего) на этот раз селектор #doesNotUnderstand: найден для получателя (который мог бы реализовать свою собственную версию или унаследовать ее от вершины иерархии классов).На этом этапе следуют шаги, описанные Adrei.

Если по какой-либо причине получатель не понимает #doesNotUnderstand: (каламбур предназначен), среда выполнения не может продолжить работу и закрывает систему (что еще она может сделать?)

Обратите внимание, что поиск немного отличается, если сообщение было отправлено на super.Но это уже другая история, и основные идеи этого вопроса остаются.

0 голосов
/ 02 февраля 2019

Отладчик открывается как ответ на необработанное исключение.Чтобы лучше объяснить, мы можем начать с запуска исключения, которое не обнаруживается нигде в системе.Например, мы можем выполнить на игровой площадке Error signal: 'an error'. (сигнал выдаёт ошибку в Pharo).Откроется следующий отладчик:

enter image description here

Когда происходит исключение, система сначала пытается найти обработчик исключения для этого исключения.Если обработчик исключений не найден, система отправляет сообщение defaultAction исключению.Это реализовано в классе Error как:

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 со следующей реализацией:

UnhandledError>>#defaultAction
    <reflective: #unhandledErrorDefaultAction:message:>
    ^ UIManager default unhandledErrorDefaultAction: self exception

Метод unhandledErrorDefaultAction: довольно прост и просто отправляет объекту исключения сообщение debug.

MorphicUIManager>>#unhandledErrorDefaultAction: anException
    anException debug

Метод отладки реализован в Exception, корневом классе всех исключений в Pharo:

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 не перехвачен, он просит менеджер пользовательского интерфейса обработать этот случай;
  • менеджер пользовательского интерфейса отправляет сообщение debugпервоначальное исключение, в данном случае исключение MessageNotUnderstood (это делает только MorphicUIManager; другие менеджеры пользовательского интерфейса, такие как CommandLineUIManager, выполняют другие действия, например, создание образа);
  • сообщение debug открывает отладчик

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

Если вы попытаетесь выполнить код, содержащий неизвестный класс, например UnnknowsClass new., компилятор также обнаружит это и спросит пользователя, что делать.В этом случае не возникает исключений.

Есть и другие помощники, которые используют тот же механизм, что и doesNotUnderstand:, например, для получения уведомлений.Если вы выполняете Object new notify: 'a notification', метод notify: генерирует исключение Warning, которое заканчивается открытием отладчика.

enter image description here

...