[英]How does Pharo starts debugger when message is not understanded?
調試器將作為對未處理異常的響應而打開。 為了更好地解釋,我們可以從觸發系統中未捕獲的異常開始。 例如,我們可以在Playground Error signal: 'an error'.
執行Error signal: 'an error'.
(信號在Pharo中拋出錯誤)。 這將打開以下調試器:
發生異常時,系統首先嘗試為該異常查找異常處理程序。 如果未找到異常處理程序,則系統將消息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
方法debug在Exception
實現,Pharo中所有異常的根類為:
Exception>>#debug
"open a debugger on myself"
Processor activeProcess
debug: self signalerContext
title: self description
這就是打開調試器的原因。
在向對象發送未知消息的情況下,方法Object>>#doesNotUnderstand:
拋出MessageNotUnderstood
類型的異常。 此異常遵循與之前相同的鏈,系統最終將debug
消息發送到MessageNotUnderstood
異常,從而打開調試器。
簡而言之:
#doesNotUnderstand:
; doesNotUnderstand:
引發MessageNotUnderstood
類型的異常; UnhandledError
異常; UnhandledError
它會要求UI管理器處理這種情況; debug
發送到初始異常,在這種情況下是MessageNotUnderstood
異常(只有MorphicUIManager
執行此操作;其他UI管理器如CommandLineUIManager
執行其他操作,如現有映像); debug
消息打開調試器 不存在的變量的處理程序具有與實際編譯器完全不同的實現。 當代碼在具有未知變量的類中編譯時,編譯器會檢測到該代碼並詢問用戶要執行的操作:創建新的實例變量或本地參數。
如果您嘗試執行包含未知類的代碼,例如UnnknowsClass new.
編譯器還檢測到這一點並詢問用戶該做什么。 在這種情況下沒有例外。
還有其他幫助程序使用與doesNotUnderstand:
相同的機制doesNotUnderstand:
例如,引發通知。 如果執行Object new notify: 'a notification'
方法notify:
拋出一個Warning
異常,最終打開調試器。
為了補充Adrei Chis給出的優秀答案,讓我補充一下,消息#doesNotUnderstad:
與其他消息有點不同。
每次發送消息時,運行時(通常在虛擬機中)都會找到與正在發送的消息的選擇器的預期接收者相對應的方法。
它通過查看接收者的行為來做到這一點。 如果沒有找到方法,則轉到繼承的行為(通常是超類中定義的行為),並繼續這種方式直到找到方法或繼承鏈用盡。 此搜索稱為方法查找 。
在第二種情況下(當對象的行為層次結構中不存在任何方法時),Runtime(1)通過創建具有未找到選擇器的Message
對象和實際參數(如果有)和(2)發送接收一個帶有選擇器#doesNotUnderstand:
和參數消息剛剛具體化。
查找過程重復,並且(很可能)這次為接收器找到了選擇器#doesNotUnderstand:
它可以實現自己的版本,或者從類層次結構的頂層繼承它)。 此時,Adrei描述的步驟如下。
如果由於任何原因接收器不理解#doesNotUnderstand:
雙關語),運行時無法繼續並關閉系統(它還能做什么?)
另請注意,如果將消息發送到super
,則查找會略有不同。 但這是另一個故事,而這個問題的基本思想仍然存在。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.