在一般的開發中,Java的單繼承限制一般不會引起什么問題。實際上,需要使用多重繼承往往意味著糟糕的設計。然而還是存在一些情況,程序員們希望能夠繼承多個類。雖然Java不允許繼承多個類,但是有些技巧能夠模擬多重繼承。
我在Swing應用程序和Web應用中都使用過這個技巧。Swing應用打包并部署服務到應用服務器上。這種情況下,因為我希望在不同組件間拖放對象而這些GUI組件共享同一個拖放方法,這樣的話,所有GUI組件需要擴展兩個類:GUI組件本身(JTree或JList)和通用的拖放類(drag-and-drop class)。本文中介紹的技術簡化了拖放類的實現。
為了更好的闡述Java中多重繼承的技術,讓我們先來如何在一個Web應用中使用它。在這個Web應用中,Servlet類和其他類需要被擴展。我的這個應用很簡單,是一個基于文本的信息傳遞系統,能夠通過移動電話、PDA或者其他網絡終端設備傳遞信息給另一個移動電話。

如上圖所示,這個系統的核心是一個能夠從客戶端接受信息然后傳遞給移動電話的服務。為了簡化客戶端開發,我寫了一個MessageClient類來包含所有用于與服務通信的通用方法。因為這個類可以最為基類被所有可能的終端設備使用,因此能夠簡化客戶端開發。
MessageClient類的源代碼如下:






































































?
這個類包含3個方法:
sendMessage()方法將實際信息發送到服務器;
connectServer()方法負責連接服務。在本例中,服務是一個RMI服務;
getServerName()是一個抽象類,因為不同設備決定服務名字的方式不同。也就是說,任何繼承自MessageClient的類都必須實現getServerName()方法。
在開發與信息服務通信的客戶端程序時,我們需要多重繼承。我們的網絡客戶端是一個簡單的用來接收來自表單的信息并將其傳送到服務器的Servlet。為了完成上述任務,這個Servlet必須既繼承HttpServlet又繼承MessageClient。由于Java不允許這種繼承行為,我讓主類繼承HttpServlet,讓主類中的內部類繼承MessageClient,然后外部類創建了內部類的一個實例。代碼如下:

public?class?SendMessageServlet?extends?HttpServlet
{

???private?MessageClient?m_messageClient;
???private?String?m_serverName;

???public?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)

?????????throws?ServletException,?IOException
{

??????try
{
????????//Get?server?name
?????????m_serverName?=?request.getServerName();
?????????System.out.println("ServerName?is?"?+?m_serverName);
?????????//Create?message?client?to?communicate?with?message?server
?????????m_messageClient?=?new?ServletMessageClient();
?????????System.out.println("Created?Message?Client");
?????????m_messageClient.connectToServer();

?????????//Get?message?and?phone?number
?????????String?phoneNum?=?(String)?request.getParameter("PhoneNum");
?????????String?message?=?(String)?request.getParameter("Message");

?????????//Send?message
?????????m_messageClient.sendMessage(phoneNum,message);

?????????//Display?page?to?tell?user?message?was?sent
?????????response.setContentType("text/html");
?????????RequestDispatcher?dispatcher?=?getServletContext().getRequestDispatcher("/SendMessageForm.jsp");
?????????dispatcher.include(request,?response);

??????}catch?(Exception?e)
{
?????????e.printStackTrace();
??????}
???}?

???public?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)

?????????throws?ServletException,?IOException???
{
??????doGet(request,?response);
???}


????/**?*//**?Inner?class?used?to?extend?MessageClient?????*/

????public?class?ServletMessageClient?extends?MessageClient?
{

???????public?ServletMessageClient()
{
?????????super();
???????}

???????public?String?getServerName()
{
??????????System.out.println("Returning?ServerName?"?+?m_serverName);
??????????return(m_serverName);
???????}
????}
}?
這種方法并不是真正的多重繼承,因為我們使用了代理(例如:MessageClient被很多外部類繼承,但并不是外部類本身),但是效果是一樣的。雖然MessageClient能被單獨的類擴展,但是使用內部類允許它訪問外部類中的所有成員和方法。這讓兩個類之間的交互變得很容易。這個例子只擴展了兩個類,你當然可以使用這種技術擴展任意多類。
當然,其實這個信息傳遞服務的例子不用多重繼承也能實現。如果MessageClient有一個能夠接收服務服務名字的構造函數,那么getServerName()方法就可以不是抽象的。這意味著Web客戶端可以不必繼承MessageClient類。
最后提醒開發者,只有在有明確的理由,確定要使用上面技術時才使用,并且使用時要小心。因為多重繼承使設計變得復雜,并且很容易被誤用。