簡體   English   中英

當消息未被明確時,Pharo如何啟動調試器?

[英]How does Pharo starts debugger when message is not understanded?

當您啟動代碼發送未實現的消息時,Pharo啟動調試器。

據我所知,它通過Object >> doesNotUnderstand ,它觸發異常,這導致調試器窗口。

在此輸入圖像描述

問題是Object >> doesNotUnderstand做了什么,以及與其他交互式幫助器有什么不同,比如從不存在的變量開始?

調試器將作為對未處理異常的響應而打開。 為了更好地解釋,我們可以從觸發系統中未捕獲的異常開始。 例如,我們可以在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管理器處理這種情況;
  • 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM