Multiple Inheritance in Java

By

Most Java developers will have heard the phrase “Java does not support multiple inheritance”, or maybe even admitted that they “wish Java supported multiple inheritance”.

A rarely asked counter-question is “Have you tried?”.

I have.

I set myself the task of creating a working implementation of multiple inheritance within Java. The requirements for a solution were:

  • The inheriting class must have access to all of the inherited class methods and data.
  • It must do this without using composition.
  • It can be used anywhere a traditionally inherited class could be used.
  • It can be defined without writing boilerplate code.
  • It can be created and used without boilerplate code.

The result was an almost compete implementation of multiple inheritance, with a handful of lines in one class, using only core Java functionality. This included one solution which inherits and exposes all public methods exposed by its parent classes, as well as an alternative solution which only exposed the child class’ public methods (hidden inheritance).

Below you will find two main methods, illustrating the two types of multiple inheritance which have been implemented. You can also find references to the source files, if you wish to try it out.

The implementation class will inherit from the Runnable interface, an ArrayList concrete class, a Properties class, and finally its own Greetings interface. These classes and interfaces where chosen for the following reasons:

  • Runnable, so that the class can have a method run in another thread.
  • ArrayList, as an example of a concrete class that has an interface.
  • Properties, as an example of a concrete class the does not have an interface.
  • Greetings, for a custom, locally defined interface.
In the full multiple inheritance example, I used a shutdown hook, to print the final state of the object which has been executing in a separate thread, before exiting.

Hidden Multiple Inheritance

Hidden inheritance is a particular subset of inheritance. From the point of view of the child class, all the parent class’s behaviour is accessible as though it were a normal ‘extends’ inheritor. However, it is not polymorphic in terms of its external interface or its cast-ability. The child’s public signature only includes those things which are explicitly listed in its own code, and not anything from its parent.

There are practical uses for this. If you want to have a class which is a HashMap ‘under the hood’, but should not expose the built-in HashMap methods put(x,y) or remove(x), then this a way to achieve that.

The following code creates an instance of the Greetings implementation class, which uses hidden multiple inheritance. Be sure to read the comments, as they describe what is going on.

public static void main(String[] args)
{
    // Create instance that does not expose access to the
    //  public methods methods of the inherited classes.
    final Greeting.Hidden hidden = Greeting.Create.hidden();

    // print a greeting, in includes the contents of the
    //  List and Properties portions of itself.
    hidden.hello();
}

Full Multiple Inheritance

Like the hidden multiple inheritance described earlier, this form of inheritance gives the child class full access to its parent classes. This solution goes one step further though, by making the class also share the interface of its parent classes in true, polymorphic fashion.

The following code creates an instance of the Greetings implementation class, but this time it exposes the interfaces of the classes it inherited from.

private static void main(String[] args)
{
    // Create instance that exposes the full access to all
    //  of the public methods of inherited classes
    final Greeting.Full full = Greeting.Create.full();
    full.hello();

    // Run the hello() method before exiting, to printout
    //  the final inherited state.
    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable()
    {
        public void run()
        {
            full.hello();
        }
    }));

    // Set some more state
    full.add(6);
    full.setProperty("Seven", "7");
    full.setProperty("Eight", "8");

    // use the Runnable interface to add some more state
    //  from another thread.
    new Thread(full).start();

    // print the state before exiting (Runtime hook will
    //  print final state).
    full.hello();
}

The following is an example of a class called Greeting that inherits from multiple other classes. Yes, it is an interface rather than a class, which was done as part of an effort to make the definition and use of this pattern more friendly.

interface Greeting
{
    public interface Hidden
    {
        public void hello();
    }

    public interface Full extends Hidden, List
    {
        // These have been included, because Properties
        //  does not implement an interface.
        public Object setProperty(String key, String value);
        public String getProperty(String key);
        public String getProperty(String key, String defaultValue);
        public SetstringPropertyNames();
        public EnumerationpropertyNames();
        public void list(PrintWriter out);
        public void list(PrintStream out);
        public void load(Reader reader) throws IOException;
        public void load(InputStream inStream) throws IOException;
        public void store(OutputStream out, String comments);
    }

    public class Create
    {
        // only expose the main class interface
        public static Hidden hidden()
        {
            return MultipleInheritanceFactory.hidden(Create.class);
        }

        // expose all of the interfaces.
        public static Full full()
        {
            return MultipleInheritanceFactory.full(Create.class, Full.class);
        }

        // define the multiple inheritance class
        private class A extends Properties
        {
            private class B extends ArrayList
            {
                private class C implements Runnable
                {
                    // The MultipleInheritanceFactory
                    //  returns an instance of this class.
                    private class Impl implements Hidden
                    {
                        private Impl()
                        {
                            add(1);
                            setProperty("Two", "2");
                            add(3);
                            setProperty("Four", "4");
                            add(5);
                        }

                        // Says hello, and prints the state
                        //  of the inherited classes.
                        @Override public void hello() { ... }
                    }

                    // Adds state for a couple of seconds,
                    //  adding state every half a second,
                    //  alternating between Properties and
                    //  List part of the implementation.
                    @Override public void run() { ... }
                }
            }
        }
    }
}

The following is the multiple inheritance factory method, that creates an instance of an instance of the class, but only exposes the public methods of the implementation class. It is declared as a generic so that it can be used for any combination of inherited classes and interfaces without modification.

public static H hidden(Class miContainer)
{
    try
    {
        ClassparentClass = null;
        ClassimplClass = miContainer;
        Object implObject = implClass.newInstance();

        // Create an instance of the outer most class, and
        //  then use it to create the next class in the
        //  inheritance. Repeat until the implementation
        //  class has been created.
        do
        {
            Class[] declaredClasses = implClass.getDeclaredClasses();
            if ((declaredClasses != null) && (declaredClasses.length > 0))
            {
                parentClass = implClass;
                implClass = declaredClasses[0];
                Constructorconstructor = implClass.getDeclaredConstructor(new Class[] {parentClass});
                constructor.setAccessible(true);
                implObject = constructor.newInstance(new Object[] {implObject});
                constructor.setAccessible(false);
            }
            else
            {
                implClass = null;
            }
        }
        while (implClass != null);

        return (H) implObject;
    }
    catch (Exception e)
    {
        throw new RuntimeException("Can not instanciate : " + miContainer.getName(), e);
    }
}

The following is the multiple inheritance factory method, that creates an instance of an instance of the class, but this time it is using a proxy to expose the public methods of all of the inherited classes as well.

public static F full(final Class miClass, Class... interfaces)
{
    try
    {
        return (F) Proxy.newProxyInstance(miClass.getClassLoader(), interfaces, new InvocationHandler()
        {
            Object implObject = hidden(miClass);

            @Override
            public Object invoke(Object proxy, Method method, Object[] parameters) throws Throwable
            {
                Method requiredMethod = null;
                String methodName = method.getName();
                Class[] paramTypes = method.getParameterTypes();
                try
                {
                    Object currentObject = implObject;
                    // start from the implementation object
                    //  and step though enclosing parent
                    //  objects, until the required method
                    //  is found.
                    while ((currentObject != null) && (requiredMethod == null))
                    {
                        try
                        {
                            Class objectClass = currentObject.getClass();
                            requiredMethod = objectClass.getMethod(methodName, paramTypes);
                        }
                        catch (Exception e)
                        {
                            try
                            {
                                Field parentObjectField = currentObject.getClass().getDeclaredFields()[0];
                                currentObject = parentObjectField.get(currentObject);
                            }
                            catch (Exception ee)
                            {
                                currentObject = null;
                            }
                        }
                    }

                    // run the required method
                    if (requiredMethod != null)
                    {
                        return requiredMethod.invoke(currentObject, parameters);
                    }
                    else
                    {
                        throw new RuntimeException("Could not find required method: " + method.getName());
                    }
                }
                catch (Exception e)
                {
                    throw new RuntimeException("Could not invoke required method: " + method.getName());
                }
            }
        });
    }
    catch (Exception e)
    {
        throw new RuntimeException("Could not create object: " + miClass.getName(), e);
    }
}

These code samples are completely Java 5 compliant, which indicates that if a future version of Java was to include multiple inheritance syntactically, there is a good chance it could be compiled to run on older versions of the JVM.

You may have noticed the word “almost” in my previous statement. There are some restrictions as to what can be done with this class. Due the fact that this implementation uses the build in Java proxy system, the resulting object must be an implementation of a series of interfaces. This means the resulting (proxy) class cannot be cast to the concrete class parent class, even though it has inherited all of the same behaviour. This is a problem with classes like Properties, where the concrete class itself is usually passed around.

If you would like to play around with the actual code, you will find it in a zip file attached to this entry.

Source code: Multiple-Inheritance-in-Java

Leave a Reply