簡體   English   中英

squeak(smalltalk) 如何獲取對象的所有方法(繼承方法也是如此)

[英]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 本身中定義。

顯示協議瀏覽器的屏幕截圖,顯示 allSelectors 方法的代碼

由於以下原因,這很有趣。 乍一看,人們可能會想到這樣的表達方式

  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.

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