2012-07-08 74 views
4

請允許我解釋我正在嘗試做什麼 - 我認爲標題可以粗略地解釋它,但我不太確定我是否正在處理事情如果我錯了,請糾正我的錯誤!將函數作爲字符串傳遞的正確方法

我使用LayeredPane創建了自定義對話框。基本上jPanel顯示在POPUP_LAYER上,因此出現在主要內容的頂部。此面板包含一個簡單的'label-textbox-okay-cancel'控件組。我將這稱爲'對話框面板'。

我是什麼要做: 當單擊主窗口(包含在LayeredPane內)上的按鈕時,對話框面板將出現,並允許用戶輸入一些文字,然後點擊確定或取消。這很簡單,但我希望此代碼可以重複使用,這意味着主窗口上的其他按鈕將調用相同的對話框面板,但標籤中的文本不同。

這當然要求我包含某種回調函數,以便Dialog Panel上的okay按鈕將根據調用它的按鈕來運行正確的代碼。

我目前的嘗試是存儲一個字符串,其中將包含當用戶單擊對話框面板上的OK按鈕時應運行的功能的名稱。我試圖檢索這個字符串並將其轉換爲函數名稱,到目前爲止,我已經找到許多對「反射」的引用,其中許多提示它不是一個好主意。

在我一直無法得到任何示例代碼的工作,因爲我不明白什麼是「OBJ」是在下面的代碼,但無法調用的方法無論如何:

method = obj.getClass().getMethod(myCallbackString); 

我的問題是:

首先,我是否正在以正確的方式進行?我更願意接受建議,但請儘量保持簡單,因爲我真的剛剛開始!

其次,上面顯示的代碼中的'obj'是什麼?我真的很想知道,即使這不是我應該做的事情!

我的其他想法包括:我的Dialog Panel是否應該在它自己的類中,如果是,再次如何傳遞迴調函數?

任何幫助或建議將受到感謝。

順便說一句:回答「爲什麼不使用正常對話框?」的問題。我只能說我目前正在試驗,而我只是想看看我能否做到這一點!

MVK

+1

'getMethod'只有在方法公開的情況下才能使用。如果它是私人的,你需要使用'getDeclaredMethod'。獲取方法後,需要調用它:'method.invoke(obj,anyParameters)',其中obj是要調用該方法的對象。 – 2012-07-08 13:03:23

+1

我認爲使用'switch'語句選擇要調用的方法可能更明智。 – 2012-07-08 13:09:25

回答

2

obj名字你想調用其方法的對象,你的情況,也許可以與this更換(或刪除它完全,因爲this是暗示):

private void callByName(String name) { 
    try { getClass().getMethod(name).invoke(this); } 
    catch (RuntimeException e) { throw e; } 
    catch (Exception e) { throw new RuntimeException(e); } 
} 

對於這個工作你需要用適當的名稱聲明公共的無參數方法。

+0

非常感謝Marko,當我測試它時,這段代碼就工作了 - 我會接受這個答案,因爲它實際上回答了這個問題,但我已經注意到在使用這種方法時存在潛在的問題。 – MaxVK 2012-07-08 14:26:30

+0

是的,存在問題,但是由於您正在學習,嘗試它並查看您是否自己解決問題並不是一種罪過。 – 2012-07-08 14:27:39

1

我還沒有與JPanel的工作,但我的理解表格,答案似乎很簡單。爲什麼不在接口上工作並傳遞該接口的不同實現,而不是傳遞方法名稱?

5

通過Java程序傳遞迴調函數的常用方式是通過傳遞實現特定回調函數的接口實例。匿名實現界面是典型的,但不是必需的。

例如,這裏是一個接口:

interface MyCallback { 
    void performCallback(); 
} 

這裏是你定義你的對話框的方法,需要一個回調的方式:

void openWithCallback(MyCallback cb) { 
    // Do something useful... 
    ... 
    // Perform the callback 
    cb.performCallback(); 
} 

這裏是你調用該方法的方式:

public void OpenDialog() { 
    myDialog.openWithCallback(new MyCallback() { 
     public void performCallback() { 
      System.out.println("Inside callback..."); 
     } 
    }); 
} 
+0

非常感謝dasblinkenlight,我現在已經採用了另一種方法,但我也會在某些時候嘗試。 – MaxVK 2012-07-08 14:28:25

2
  1. 我認爲你的想法是Val id,儘管它有一個主要缺點:在代碼中將方法名稱存儲爲簡單的字符串,因此編譯器無法檢查它們的有效性。因此,如果更改方法的名稱,則必須手動確保更新了引用該方法的所有字符串。 這通常意味着'反射是一個壞主意'。
  2. obj在您的代碼中是您要調用方法的對象。作爲一個簡單的例子,someInteger.toString();的等值反射將是someInteger.getClass().getMethod("toString").invoke();

在一個更通用的音符,一旦你熟悉的Java,你可能還檢查了像斯卡拉,其中功能是有規則物體的功能性語言,你想讓你的情況可能與完整的編譯器檢查來實現。

+0

感謝tehlexx,注意到您對檢查有效性的擔憂,儘管在這種情況下它並不是一個真正的問題。我會在某個時候看看Scala,謝謝你的建議。 – MaxVK 2012-07-08 14:21:50

+0

偉大的,快樂的學習! – tehlexx 2012-07-09 08:34:58

2

我認爲你正在使這種的方式比它必須更復雜。你說你想要這個:

This is all easy enough, but I would like this code to be re-usable, which means 
that other buttons on the main window will invoke the same Dialog Panel, but with 
different text in the label. 

根據定義,DialogBox是可重用的。爲什麼不單單按鈕點擊偵聽器在單擊時將適當的文本傳遞給對話框,以便顯示正確的信息?

如果需要具體的行動取決於調用該對話框上的按鈕,點擊後發生,你可能要考慮:

  1. 創建的自定義對話框擴展,包括邏輯,知道做基於什麼誰打電話給他。然後,當一個按鈕調用自定義對話框時,它會傳遞一個參數讓對象在關閉對話框後知道它想做什麼。

  2. 看看使用抽象工廠模式。

是的,你可以通過反射來做到這一點。是的,這將是一個非常糟糕的主意,原因是多方面的,其他人在其他的答案已經討論過,尤其是如果這是生產代碼(儘管你似乎表明它是一個實驗。)

如果你真的只是想看看如何用反思來工作,你可能想要閱讀這個話題。我發現this是更好的教程之一。

+0

感謝Roddy,是的,它現在是一個實驗,儘管我很可能會嘗試幾種不同的方法來獲得相同的結果,包括您建立自定義DialogBox的建議,謝謝。 – MaxVK 2012-07-08 14:20:39

相關問題