[英]squeak(smalltalk) how to get all the methods of an object (inherited methods too)
我怎樣才能得到一個對象可以理解的所有方法的列表?
例如:
set := 8 getAllMethods
將給我所有方法8
可以理解的set
在代碼中,您可以使用allSelectors
:
set := 8 class allSelectors
為您提供一組 8 可以理解的所有消息名稱(又名選擇器)。
如果您需要 CompiledMethods 而不僅僅是消息名稱,您可以使用lookupSelector:
| class |
class := 8 class. "will be SmallInteger"
set := class allSelectors collect: [:each | class lookupSelector: each]
如果您不想在代碼中執行此操作,而是想在 IDE 中找出對象可以理解的消息,那么我建議使用協議瀏覽器(又名 Lexicon 工具)。 您可以通過類的上下文菜單中的“瀏覽協議”打開它:
我用它來查找 allSelectors 和 lookupSelector:,它們是從 Behavior 繼承的,並沒有在 Class 本身中定義。
由於以下原因,這很有趣。 乍一看,人們可能會想到這樣的表達方式
anObject class withAllSuperclasses gather: [:class | class methodDictionary]
它收集了類及其超類中實現的所有方法。 但是,如果在類及其超類中定義了一個方法,我們應該忽略后者,因為anObject
將使用類中的方法。
為了彌補上述腳本的這種副作用,我們只需要收集在更接近anObject class
的類中定義的方法。 一種方法是從上到下枚舉類,將它們的所有方法添加到Dictionary
。 由於字典將只保留添加到給定key
的最后一個元素(在本例中為selector
),因此只有屬於anObject
協議的anObject
才會存活:
methods := Dictionary new.
anObject class withAllSuperclasses reverseDo: [:class |
methods addAll: class methodDictionary associations].
注意使用reverseDo:
向下枚舉類。
另一種方法是從下到上枚舉類,檢查選擇器是否已經被訪問過:
methods := Dictionary new.
anObject class withAllSuperclasses do: [:class |
class methodDictionary do: [:cm |
methods at: cm selector ifAbsentPut: [cm]]]
(是cm
代表CompiledMethod
)
第二個版本有點長,更復雜(它有兩個循環,一個嵌套在另一個循環中)並且需要條件邏輯( #at:ifAbsentPut:
。 換句話說,它不應該是被選中的那個。
筆記
在尋找創建集合(在本例中為對象理解的所有方法的集合)的方法時,首先要確保您確實需要這樣的集合。 例如,如果您想在屏幕上顯示它,您將需要該集合。 但是,如果您只想將集合用於成員資格檢查,則可能還有其他方法可以繼續。 在您的情況下,您可以簡單地詢問對象:
anObject respondsTo: <selector>
如果答案為true
,請使用恢復該方法
anObject class lookupSelector: <selector>.
這既簡單又高效,因為它不會創建集合等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.