2010-05-18 151 views
6

我正在寫(完善)Java的「擴展」,這將有助於角色編程。
我使用javacc將我的代碼翻譯成Java代碼。我的編譯器爲每個聲明的類添加一些代碼。這裏有一個例子要更清楚:Java:擴展對象類

MyClass extends String implements ObjectWithRoles { //implements... is added 
    /*Added by me */ 
    public setRole(...){...} 
    public ... 
    /*Ends of stuff added*/ 
    ...//myClass stuff 
} 

它增加了實施..和必要的方法,你每個單一類的聲明。相當粗糙,不是嗎?

如果我在一個類中編寫我的方法,並且所有類擴展了..但是..如果類已經擴展了另一個類(就像這個例子),會更好嗎?

我不想創建一種管理角色的包裝,因爲我不希望程序員必須知道比Java更多的東西,幾個新的保留字及其用法。

我的想法是擴展java.lang.Object ..但你不能。 (對吧?)
其他想法?

我在這裏是新的,但我關注這個網站,所以謝謝你的閱讀和所有你給的答案! (我很抱歉英語,我是意大利語)

+4

您不能擴展'String'。這是一個最終的類,你不能繼承它的子類:http://java.sun.com/javase/6/docs/api/java/lang/String.html – 2010-05-18 08:30:16

+2

「我的想法是擴展java.lang。對象..但是你不能。(對吧?)「 嗯,我會說,任何類沒有擴展子類對象默認情況下。 – 2010-05-18 09:23:57

+1

@James P.我認爲法比奧的意思是用他自己的更新版本替換Object。這可以做到,爲您自己的應用程序創建一個通用的基類,並從那裏擴展所有內容。但你不想添加,自動擴展到一切:) – extraneon 2010-05-18 09:42:58

回答

6

如果它只是一個「研究」項目,您想在其中探索這種擴展如何工作,您可以提供自己的Object類的實現。只需複製現有的對象實現,添加setRole方法等,然後將-Xbootclasspath:.:/usr/lib/jvm/java-6-sun/jre/lib/rt.jar作爲java命令的參數。 (在尋找真正的rt.jar之前,我會查找.中的api類。)

+0

我試圖實現您的解決方案:在我的方法修改的目錄(。)java/lang/Object.java中添加Object文件。它編譯(所以它找到的方法),但當我嘗試執行我得到NoSuchMethodError ..我用-Xbootclasspath和-classpath具有相同的結果。 (Javac甚至沒有這個工作!) – 2010-05-18 15:15:05

+0

你應該添加Object.class,而不是在'.'目錄下,而是在'./java/lang'目錄下。 – aioobe 2010-05-18 15:18:32

+0

愚蠢的英語..我已經做到了,我已經複製了Java/lang英寸。它編譯但不執行。對不起.. – 2010-05-18 19:56:23

3
  • 你可以延伸Object - 每個類都擴展它。
  • 你似乎需要類似多重繼承的東西 - Java中沒有這樣的東西
  • 如果你想添加功能,使用對象組合。即,

    YourClass extends Whatever implements ObjectWithRoles { 
        private RoleHandler roleHandler; 
        public RoleHandler getRoleHandler() {..} // defined by the interface 
    } 
    

然後所有的方法都放在RoleHandler

+0

當我說「擴展對象」時,我想創建一個對象的超類,這不是正確的術語,對不起。 無論如何,你的答案是有用的,我會檢查是否是解決方案。謝謝。 Fabio F. – 2010-05-18 08:37:20

+3

等待,我認爲他在談論擴展Object類,爲所有對象添加功能 – 2010-05-18 08:39:39

3

您應該考慮使用組成,而不是的傳承來解決這個問題;這樣你就可以提供你需要的功能,而不需要繼承你的「一次性」。

例如,JDK提供的類別爲PropertyChangeSupport,可用於管理PropertyChangeListener和觸發PropertyChangeEvent s。如果您希望編寫一個觸發PropertyChangeEvent的類,則可以嵌入PropertyChangeSupport實例變量並將所有方法調用委託給該類。這個避免了繼承的需要,並且意味着您可以用新功能補充現有的類層次結構。

public class MyClass extends MySuperClass { 
    private final PropertyChangeSupport support; 

    public MyClass() { 
    this.support = new PropertyChangeSupport(this); 
    } 

    public void addPropertyChangeListener(PropertyChangeListener l) { 
    support.addPropertyChangeListener(l); 
    } 

    protected void firePropertyChangeEvent() { 
    PropertyChangeEvent evt = new ... 
    support.firePropertyChangeEvent(evt); 
    } 
} 
1

如果你在做你正在做的事情,那麼繼承可能不是正確的習慣用法。您可能需要考慮裝飾器模式,從而構建一個以其功能較少的其他類爲參數的類,併爲其添加一些附加功能,將現有類委託給已存在的功能。如果實現對於許多裝飾器來說很常見,那麼您可能需要考慮將該功能放在可以共享的類中,並且可以將其委託給所有裝飾器。根據你的需要,雙重派遣或反射可能是適當的,以便爲各種各樣的類製作類似但不完全相同的裝飾器。

另外,正如在註釋中指出的那樣,String被聲明爲「final」,因此不能被擴展。所以,你應該真的考慮一個解決方案,讓你委託/裝飾對象。例如,您可能有一些對象封裝了一個字符串,並通過getString()或toString()提供對該字符串的訪問權限,但是會在String類的頂部添加其他功能。

如果您只想將某些對象與其他屬性相關聯,請使用Map(例如HashMap)。

+1

1)沒有「頂層包」這樣的東西。 2)名爲「對象」的類絕對不會被同一包中的其他類自動擴展。 – 2010-05-18 08:39:20

+1

我100%肯定從未在任何符合標準的JVM中工作。 – 2010-05-18 08:49:54

+0

@邁克爾,沒關係,我想我可能一直與AS3或其他語言混淆,最終的超類與類似的黑客。 – 2010-05-18 08:51:09

2

如果您正在討論將角色添加到所有對象,我還會考慮基於註釋的解決方案。你會用類似@Role(「User」)的類來註釋你的類。在另一個類中,可以提取角色值並使用它。

我認爲它需要帶有運行時間保留的註釋,您可以使用反射來檢查運行時註釋是否存在,並使用getAnnotation獲取該註釋。我覺得這會比自動擴展所有類更清潔。

我相信有一些框架完全使用這樣的解決方案,所以應該有一些示例代碼。

1

你真正想要做的是monkey patching,即改變現有類的行爲而不修改它們的代碼。

不幸的是,Java不支持這個功能,也沒有像mixins這樣的東西可以替代使用。所以除非你願意改用像Groovy這樣的更加動態的語言,否則你將不得不使用不太優雅的解決方案,比如合成。

+0

您不一定需要動態類型語言,例如Groovy或Ruby來執行猴子修補或mixin - 一些靜態語言(例如Scala)也支持mixins,並且您可以在Scala中使用「皮條客我的圖書館「模式。 – Jesper 2010-05-18 12:23:39