Simulate multiple inheritance in Java
A trick for extending multiple classes
By Thomas Hammell, JavaWorld.com, 10/24/05
- Digg
- Reddit
- SlashDot
- Stumble
- del.icio.us
- Technorati
- dzone
Java's single inheritance limitation is usually not a problem in the normal course of development. In fact, the need to use
multiple inheritance could be a sign of a bad design. There are times, however, when developers wish they could extend more
than one class. Although Java prevents a developer from extending more than one class, a simple trick can be used to simulate
multiple inheritance.
I have used this technique in both a Swing application and a Web-based application. The Swing application packaged and deployed
services to application servers. In that case, I needed multiple inheritance because I was adding the ability to drag and
drop objects between the different components of the GUI and wanted all the GUI components to share the same drag-and-drop
methods. Thus, all the GUI components needed to extend two classes: the GUI component itself (a
JTree or
JList) and the common drag-and-drop class. The technique described in this article simplified the drag-and-drop implementation.
To illustrate my technique for simulating multiple inheritance in Java, let's examine how to use it in a Web-based application,
where the
Servlet class, along with another class, needs to be extended. The application being developed is a text-based message system used
to send text messages to a mobile phone from another mobile phone, the Web, a PDA, or some other device with access to the
Web or the phone network.
The heart of the system is a message server that receives a message from a client and forwards it to the appropriate phone.
To make client development easier, I developed a
MessageClient class to contain all the common methods needed to communicate with the message server. The class facilitates client development
because it can be used as the base class for all the possible clients.
The
MessageClient class, shown in Listing 1, contains three methods. The
sendMessage() method sends the actual message to the server.
connectToServer() connects to the message server, which, in this example, is an RMI (remote method invocation) server. The last method is
getServerName(), which is an abstract method because each device that uses this class has a different way of determining the name of the
message server. This means that all the clients that extend
MessageClient must implement the
getServerName() method.
Listing 1. 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();
}
We need multiple inheritance when developing the Web client that talks to the message server. Our Web client is a simple servlet
used to get the message from a form and send it to the message server. To complete that task, the servlet must be both an
HttpServlet and a
MessageClient. Since Java does not allow such behavior, the main class extends the
HttpServlet class, as shown in Listing 2. This main class contains an inner class that extends
MessageClient. The outer class then creates an instance of the inner class.
Listing 2. SendMessageServlet
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);
}
}
}
This approach isn't true multiple inheritance because we used delegation. (i.e.,
MessageClient is extended by a member of the outer class and not the outer class itself), but the effect is the same. Although
MessageClient could have been extended in a separate class, using an inner class allows it to access all the members and methods of the
outer class. This makes it easier for the two classes to interact.
This example only extends two classes, but there is no reason why this technique couldn't be used to extend as many classes
as needed by creating an inner class for each class that must be inherited.
Note that the message server example could have been completed without multiple inheritance. If the
MessageClient class had a constructor that accepted the server name, the
getServerName() method would not need to be abstract, which means the Web client would not have to extend the
MessageClient class. The Web client could have used the class directly. Developers should be cautious and only use multiple inheritance
if a clear reason warrants it because multiple inheritance complicates design and is easily misused.
- Digg
- Reddit
- SlashDot
- Stumble
- del.icio.us
- Technorati
- dzone
Archived Discussions (Read only)