在Java中類比多重繼承–擴充多個類的技巧

來源:互聯網
上載者:User

摘要:
雖然Java不允許多重繼承,但是有些情況卻允許其使用。本文將闡述在一個Web應用中類比多重繼承的技術。

在一般的開發中,Java的單繼承限制一般不會引起什麼問題。實際上,需要使用多重繼承往往意味著糟糕的設計。然而還是存在一些情況,程式員們希望能夠繼承多個類。雖然Java不允許繼承多個類,但是有些技巧能夠類比多重繼承。


在Swing應用程式和Web應用中都使用過這個技巧。Swing應用打包並部署服務到應用伺服器上。這種情況下,因為我希望在不同組件間拖放對象而這些
GUI組件共用同一個拖放方法,這樣的話,所有GUI組件需要擴充兩個類:GUI組件本身(JTree或JList)和通用的拖放類(drag-and-
drop class)。本文中介紹的技術簡化了拖放類的實現。

為了更好的闡述Java中多重繼承的技術,讓我們先來如何在一個Web應用中使用它。在這個Web應用中,Servlet類和其他類需要被擴充。我的這個應用很簡單,是一個基於文本的資訊傳遞系統,能夠通過行動電話、PDA或者其他網路終端裝置傳遞資訊給另一個行動電話。

如所示,這個系統的核心是一個能夠從用戶端接受資訊然後傳遞給行動電話的服務。為了簡化用戶端開發,我寫了一個MessageClient類來包含所有用於與服務通訊的通用方法。因為這個類可以最為基類被所有可能的終端裝置使用,因此能夠簡化用戶端開發。
MessageClient類的原始碼如下:

import
 java.rmi.Naming;


public
 
abstract
 
class
 MessageClient


{

   
private
 MessageServer messageServer;


   
public
 MessageClient()

   

{

      System.out.println(
"
Initializing Message Client
"
);

   }



   
/** */
/**


    * Method used to connect to the message server

    *

    * 
@param
 serverName name of the server that contains the message server

    
*/



   
protected
 
void
 connectToServer()

   

{

      String serverName 
=
 getServerName();

      
try


      

{

         String name 
=
 
"
//
"
 
+
 serverName 
+
 
"
/MessageServer
"
;

         messageServer 
=
 ((MessageServer) Naming.lookup(name));

      }



      
catch
(Exception e)

      

{

         System.out.println(
"
Error connecting to Message Server.  Exception is 
"
 
+
 e);

         e.printStackTrace();

      }



   }




   
/** */
/**


    * Method used to send message to server

    *

    * 
@param
 phoneNum phone number to send message to

    * 
@param
 message message to send

    
*/



   
public
 
boolean
 sendMessage(String phoneNum, String message)

   

{

      
try


      

{

         
return
(messageServer.sendMessage(phoneNum,message));

      }



      
catch
(Exception e)

      

{

         System.out.println(
"
Error Sending Message.  Exception is 
"
 
+
 e);

         e.printStackTrace();

         
return
(
false
);

      }



   }




   
public
 
abstract
 String getServerName();

}

 
這個類包含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類。

最後提醒開發人員,只有在有明確的理由,確定要使用上面技術時才使用,並且使用時要小心。因為多重繼承使設計變得複雜,並且很容易被誤用。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.