Multiple Inheritance in Java

October 23, 2006 By: erik Category: Geeky, Musings, Programming 24,853 views

Rate this post:
1 Star2 Stars3 Stars4 Stars5 Stars (6 votes, average: 3.33 out of 5)
Loading ... Loading ...

I have come up with a way to accomplish multiple inheritance1 in Java using interfaces with static inner classes, which I will now present to you.

First we need to define a problem that requires multiple inheritance. Let us suppose that I have a superclass, DbObject, that allows its subclasses to be loaded from and saved to the database. We also have two abstract subclasses of DbObject, ProjectADbObject and ProjectBDbObject which provide project specific functionality to all the DbObjects of each project (see class diagram). Now let’s assume that both projects need a DbObject that can represent a tree structure, say Folder and Category for Project A and Project B respectively. This tree structure is represented by an interface that we will call SelfParenting. Like so:

public interface SelfParenting
{
  SelfParenting getParent(Database db) throws DbException;
}

Note that to fetch the actual instance, not just the foreign key reference, of our parent, we require the database.

So we have our two classes:

public class Folder extends ProjectADbObject
  implements SelfParenting
{
  private ForeignKey<Folder> parent;
  ...
  public Folder getParent(final Database db)
    throws DbException
  {
    return db.fetch(parent);
  }
  ...
}

and

public class Category extends ProjectBDbObject
  implements SelfParenting
{
  private ForeignKey<Category> parent;
  ...
  public Category getParent(final Database db)
    throws DbException
  {
    return db.fetch(parent);
  }
  ...
}

Obviously, we’re going to want more functionality than just getParent() if our interface is going to be useful. What about methods for getting the children or the depth in the tree? So we add these to our interface:

public interface SelfParenting
{
  SelfParenting getParent(Database db) throws DbException;
  SelfParenting[] getChildren(Database db) throws DbException;
  int getDepth(Database db) throws DbException;
}

And this is where we run into the multiple inheritance wall. The implementation of getChildren() and getDepth() require more than one line, and the code will be exactly the same in both Folder and Category. First, let’s look at what the code might look like for the Folder class:

public class Folder extends ProjectADbObject
  implements SelfParenting
{
  private ForeignKey<Folder> parent;
  ...
  public Folder getParent(final Database db)
    throws DbException
  {
    return db.fetch(parent);
  }

  public Folder[] getChildren(final Database db)
    throws DbException
  {
    final Collection<Folder> children =
      new ArrayList<Folder>();
    for(final Folder folder : db.fetchAll(Folder.class))
    {
      if(folder.getParent(db).equals(this))
        children.add(folder);
    }
    return children.toArray(new Folder[0]);
  }

  public int getDepth(final Database db)
    throws DbException
  {
    int depth = 0;
    Folder folder = this;
    while(folder.getParent() != null)
    {
      depth++;
      folder = folder.getParent(db);
    }
    return depth;
  }
  ...
}

Obviously, the code will be identical in the Directory class. Is there any way to avoid this code duplication? What if we put the code into static methods of a static inner class of the interface? Like so:

public interface SelfParenting
{
  SelfParenting getParent(Database db) throws DbException;
  SelfParenting[] getChildren(Database db) throws DbException;
  int getDepth(Database db) throws DbException;

  public static class Impl
  {
    public static <T extends SelfParenting>
    T[] getChildren(final Database db, final T parent)
      throws DbException
    {
      final Collection<T> children = new ArrayList<T>();
      final T[] all = db.fetchAll(parent.getClass());
      for(final T possibleChild : all)
      {
        if(possibleChild.getParent(db).equals(parent))
          children.add(possibleChild);
      }
      return children.toArray(new T[0]);
    }

    public static int getDepth(final Database db,
                               SelfParenting node)
      throws DbException
    {
      int depth = 0;
      while(node.getParent() != null)
      {
        depth++;
        node = node.getParent(db);
      }
      return depth;
    }
  }
}

Then, the implementation of the new methods shrink down to one line:

public class Folder extends ProjectADbObject
  implements SelfParenting
{
  private ForeignKey<Folder> parent;
  ...
  public Folder getParent(final Database db)
    throws DbException
  {
    return db.fetch(parent);
  }

  public Folder[] getChildren(final Database db)
    throws DbException
  {
    return Impl.getChildren(db, this);
  }

  public int getDepth(final Database db)
    throws DbException
  {
    return Impl.getDepth(db, this);
  }
  ...
}

And so the proper implementation of Category will be the same:

public class Category extends ProjectBDbObject
  implements SelfParenting
{
  private ForeignKey<Category> parent;
  ...
  public Category getParent(final Database db)
    throws DbException
  {
    return db.fetch(parent);
  }

  public Category[] getChildren(final Database db)
    throws DbException
  {
    return Impl.getChildren(db, this);
  }

  public int getDepth(final Database db)
    throws DbException
  {
    return Impl.getDepth(db, this);
  }
  ...
}

By moving the common implementation of the getChildren() and getDepth() methods into the interface (via a static inner class), we have eliminated the duplication of code, thereby enhancing the maintainability and enabling future implementations of SelfParenting to be trivial one-line methods.

The code above is obviously very inefficient2, but it was provided to demonstrate a point: that the advantages of multiple inheritance can be achieved in java via this “static methods in a static inner class in the interface” coding pattern.

Class Diagram

Multiple Inheritance Class Diagram

1Note that this accomplishes the code reuse feature of multiple inheritance only. In theory, you could get the effects of polymorphism by doing more than, or something other than, just call the static implementation in the interface.

2A proper implementation of getChildren() would involve SQL where clauses. There are also generics issues that would cause the code, as shown, to not compile. The concept remains sound.

 
  • johanatan

    I’m not a dogmatic C++ programmer, but I do enjoy having the option to use multiple inheritance. It saves you from having to ‘wrap’ all your method calls to the inner static. And, also you aren’t limited to using a static (i.e., your example could have had and used members in the interface). Of course, multiple inheritance can be abused, but ‘with great power comes great responsibility’.

    It would be really nice if there was a wrapper generator (i.e. macro) in the IDE for this sort of multiple inheritance workaround (or for the containment approach).

  • johanatan

    P.S. I wouldn’t call this a ‘flaw’ either. It’s more of a deficiency. But, I’m currently working on the Add-In that I hoped would fill in the gap. I’ll post a link to it when it’s done.

  • http://www.erik-rasmussen.com/ erik

    An “Add-In” for an IDE? Which IDE?

    Anyway, I look forward to seeing what you come up with.

  • http://www.onlinekenogames.net online keno games

    The lack of multiple inheritence is a blessing not a curse,and it should be embraced.In a decade of using java online keno gamesI have only one time encountered need for multiple inheritance, and a tiny bit of typing allowed me to use interfaces to eliminate the problem.People should pull out things like the reflection API as a last resort, and should be prepared to resign the next day.

  • Michael

    I can think of a half a dozen occasions I’ve wished for MI in the past few months. Many of the interface hacks I’ve had to use instead left a bad taste in my mouth. It’s a shame that I know what I WANT to do and are not allowed to.

    I like this solution. The only complaint I have about it is that it doesn’t allow you to inject a different implementation for the interface implementation class.

  • JavaSon

    How about inheriting from a superclass and having an inner class also inherit from a different superclass.

    • http://www.erik-rasmussen.com/ Erik R.

      Okay. What does that accomplish?

  • http://smellegantcode.wordpress.com Daniel Earwicker

    What you’ve discovered here is not multiple inheritance. It’s multiple calls to some common subroutines in order to avoid code duplication, i.e. ordinary 1970s structured programming.

    With true MI, there could be an abstract method SelfParenting.getDatabase(). The deriving class would override this to return the database, and the inherited class(es) would be able to call getDatabase() to obtain the database, instead of requiring a parameter to be passed around.

    • http://www.erik-rasmussen.com/ Erik R.

      Yes, I know. The language doesn’t allow “true MI”. However, I’ve still never seen a more elegant solution to mimicking MI in java.