30

After 20 or so years programming Java for the first time I wish I had multiple inheritance. But I don't so I'm looking for an alternative for this concrete problem.

The real application is some kind of ERP and somewhat complex so I try to translate this problem to cars. This only goes so far but it's the best I can do.

Lets start with an interface describing what a car can do:

public interface Car {

    public String accelerate();
    public String decelerate();

    public String steerLeft();
    public String steerRight();
}

Now we have a basic (but not abstract) implementation:

public class BasicCar implements Car {

    protected final String name;

    public BasicCar( String name ) {

        this.name = name;
    }

    // In the real word this method is important and does lots of stuff like calculations and caching
    protected String doDrive( String how ) {
        return name + " is " + how + "ing";
    }
    @Override
    public String accelerate() {
        return doDrive( "accelerat" );
    }
    @Override
    public String decelerate() {
        return doDrive( "decelerat" );
    }


    // This method is important, too
    protected String doSteer( String where ) {
        return name + " is steering to the " + where;
    }
    @Override
    public String steerLeft() {
        return doSteer( "left" );
    }
    @Override
    public String steerRight() {
        return doSteer( "right" );
    }
}

In the real world this itself is a facade to a DAO. Note that I need the methods doDrive and doSteer to be there because this is where the real work like some calculations, translations and caching is done.

And some more concrete implementations:

public class Sportscar extends BasicCar {

    public Sportscar( String name ) {
        super( name );
    }

    // I need to call the super method
    @Override
    public String doDrive( String how ) {
        return super.doDrive( how ) + " fastly";
    }
}

public class Truck extends BasicCar {

    public Truck( String name ) {
        super( name, new BasicMotor(), new TruckySteerer() );
    }

    // I need to call the super method
    @Override
    public String doSteer( String where ) {
        return super.doSteer( where ) + " carefully";
    }
}

What I can do right now is:

Car mcqueen = new Sportscar( "McQueen" );
mcqueen.steerLeft() //-> "McQueen is steering left"
mcqueen.accelerate() // -> "McQueen is accelerating fastly"

Car mack = new Truck( "Mack" );
mack.steerLeft() //-> "Mack is steering left carefully"
mack.accelerate() // -> "Mack is accelerating"

What I now want to do is combining these two into one which shares their functionallity:

Car red = new Firetruck( "Red" );
red.steerLeft() //-> "Red is steering left *carefully*"
red.accelerate() // -> "Red is accelerating *fastly*"

What I tried / thought about

I could copy&paste code from both into one class. But this is never a good idea. And in the real application this is pretty much code so it's an even worse idea.

I think I'm facing some major rewrite/refactoring here.

So I could make Sportscar and Truck a Decorator and for Firetruck use both. But this won't work because doSteer and doDrive are called from within the decorated objects whereas a decorator only works for calles from the "outside". So I would have to put these methods in the decorator, too and this isn't a good idea either.

So I could use Java8's new fancy features and make doSteer and doDrive delegating to an interface like:

@FunctionalInterface
interface Driver {
    public String doDrive( String where );
}

And feeding it to the constructor of BasicCar but then (apart from getting pretty complex and getting some other rather nasty java problems with final) I don't have access to the state of BasicCar in a good way anymore.

So currently I'm a little lost here. Any good ideas would be appretiated.

EDIT: To give an example how this looks in the real world: The doSteer group could be something like:

class ProductImpl {
    String getTitle(){
        return getField( "title" );
    }
    String getTeaser(){
        return getField( "teaser" );
    }
    String getField( String name ){
        Locale loc = configuredLocale();
        Map vars = configuredVarialbes();
        String value = getCached( name, loc );
        value = translateVariables( value );
        value = replaceVariables( value, vars );
        // and more
    }
}
Denham Coote
  • 634
  • 8
  • 18
Scheintod
  • 7,953
  • 9
  • 42
  • 61
  • What methods of `Sportscar` and `Truck` would a hypothetical `Firetruck` composite need to access? Just the `protected` ones you've named, or in the real world are there many such methods? – Boris the Spider Mar 26 '15 at 12:24
  • Hi Boris. There are many more. The real object is some article/product with many properties. The descendans are products like "Set" (containing sub products), "In set" (contained in sets), "matrix" (containing variants of the same product), "In matrix" (variant of the same product). The problem arises while trying to put a "matrix" in a "set" or the other way around. So the real object would be something like `extends Product_InMatrix, Product_Set`. The real properties are something like `availableAmout` which in "Sets" would be the minimum of the amount of it's contained products. and so on. – Scheintod Mar 26 '15 at 12:34
  • What's wrong with using Java8 functionality and turning them all to interfaces that have method implementations rather than abstract methods? – Necreaux Mar 26 '15 at 12:43
  • 1
    See [Stack Overflow: java traits or mixins pattern?](http://stackoverflow.com/questions/263121/java-traits-or-mixins-pattern) for some discussion of how other programming languages overcome the single inheritance limitation. Another related technique is [Stack Overflow: Java Aspect-Oriented Programming with Annotations](http://stackoverflow.com/questions/4829088/java-aspect-oriented-programming-with-annotations) – xmojmr Mar 26 '15 at 12:58
  • @Necreaux: Pretty much nothing or everything. Depending on where you stand. In my case doing this consistently (and mostly there is nothing wrong with consistency) this would mean having nearly as much interfaces as I have methods I want to override. (about 20). And the same amount (and some more for the descendent objects) of implementations of these interfaces. This becomes a great idea especially if you have many descendent classes which you can compose of these parts. It doesn't feel right if there are only few. (in my case 4-6). Same goes for Gabriel's suggestion which is basically this. – Scheintod Mar 26 '15 at 13:46
  • You're writing your own ERP from scratch, `String getTitle(){return getField( "title" );}` : just don't write your own ORM, too. – abuzittin gillifirca Mar 26 '15 at 16:08
  • I don't agree on the **Duplicate** flag. [This question](http://stackoverflow.com/questions/7493438/a-collection-of-an-abstract-class-or-something-like-that) was about how handling a collection of objects of different types in a hierarchy (by the way the question is not clear at all on why polymorphism and a collection of abstract class is not wanted by OP). This one is more focused on _Java/Single Class Inheritance/Multiple Interface Implementation_ and how to circumvent _single inheritance_ in design. Let's not be fooled because design example is with cars... – T.Gounelle Apr 01 '15 at 08:21

6 Answers6

11

You could use pattern strategy to define different behaviors and make the subclasses implement them.

Like in this picture : Pattern strategy

It's French (dictionary below) but pretty self-explanatory :

  • All the classes that inherit from Personnage are characters used in a video game.
  • All the classes that implement an interface (EspritCombatif, Deplacement, Soin) define the method in the interface. They are the behaviors.
  • The Personnage class contains an object of each of the interfaces defined on the right.
  • Each character (subclass of Personnage) chooses what code to implement by doing for example a combat = new CombatCouteau(); in the constructor.

So if you want to change only the behavior of all the guys that fight with a knife, you just change the code in CombatCouteau.


Dictionary :

  • Personnage = Character
  • Guerrier = Warrior
  • Medecin = Doctor
  • Chirurgien = Surgeon
  • Couteau = Knife
  • Pistolet = Gun
  • Marcher = Walk
  • Courir = Run
  • Premier soin = First aid
  • Opération = Surgery
  • Esprit combatif = Combative mind
  • combat, combattre = fight, to fight
  • déplacement, se déplacer = moving, to move
  • soin, soigner = healing, to heal
Gabriel
  • 734
  • 11
  • 26
  • Hi Gabriel, thanks for your answer (et le dictionnaire ;). If I understand you correctly you are proposing some variant of the `Delegate` pattern, too. In your case I would call it: *a composition of delegates*. Like I wrote in my question this is something I've been thinking about myself but the problem remains, that the delegates don't have access to the objects state. So I would have to completely "decompose" my original object. My hope was, that someone would come up with a method which doesn't include doing this :) – Scheintod Mar 26 '15 at 11:21
  • 1
    It seems everybody agrees on using some kind of composition of `Decorators` for this task. I had hoped for an more clean solution but since one day has passed and none came up I've got to swallow the pill. I'm marking this answer as correct. Not because it is more correct than the others which are great answers, too. I chose this one because it is most closely to what I'm going to use for exactly my problem at hand. The other answers are of cause perfectly valid and may be best suited for a problem similar to mine but perhaps just a little different (or for someone different.). Thank you all! – Scheintod Mar 27 '15 at 08:31
  • Hi @Scheintod, sorry for not having answered earlier. I'm sorry you didn't find any better answer but I don't think there is something better than what everything that has been suggested. However I hope you will be able to do what you need ! – Gabriel Mar 27 '15 at 08:52
4

Would a Compositor do? It does not translate to cars world smoothly, but looks suitable for your task:

public class FireTruck implements Car {

    public FireTruck( List<? extends Car> behaviors ) {
        this.behaviors = behaviors;
    }

    // I need to call the super method
    @Override
    public String doSteer( String where ) {
        String result = "":
        for (Car behavior : behaviors) result += behavior.doSteer(where);
        // post-process behavior some how to cut out infixes;
    }
}

I've assumed in your real-world app doSteer works on some domain object and not a String, so that domain object's methods set should be rich enough to compose behaviors easily in do* methods.

Victor Sorokin
  • 11,878
  • 2
  • 35
  • 51
  • In the Car Interface there's no doSteer method, how can you override something that's not there? – Larry Mar 26 '15 at 10:52
  • Thanks for your answer. If I understand you correctly this is basically a variant of the `Delegate` pattern I've been thinking about. Instead of extending the Delegate (what I was thinking about) you propose using a list of delegates (here called behaviors). But the main problem remains, that I can't access the state of `BasicCar`. – Scheintod Mar 26 '15 at 10:57
  • `doSteer` works (in some cases) indeed on `String`. In real world this is something simple like: `String getTitle(){ return getDescription( "title" ); }` where `getDescription( name )` would do the real work like accessing the right fields in the right locale, do translation, variable replacement and so on. – Scheintod Mar 26 '15 at 10:59
  • @Larry: I don't mind (very much) having to change more of my code. I'm pretty shure that I have to do it the one way or the other anyways. So if I have to put `doSteer` in the interface I won't like it very much but I could do it if it helps me solving the problem at hand. – Scheintod Mar 26 '15 at 11:02
  • @Scheintod would it be possible to arrange objects so all needed state modifications can be initiated and observed via method calls? Car example does not show any state operations, only behavior operations w/o side effects to object's state -- that's why I used name `behaviors` in my sample. If you don't use side-effects in your `FireTruck` code, you won't need state of basic object there. – Victor Sorokin Mar 26 '15 at 11:20
  • @Scheintod yes I understand why you dont like it because doSteer and doDrive is internal class methods which should not be exposed in a public interface. So what if we keep the interface as it is, extract the doSteer and doDrive out to put them into another interface, and plug the new interface to car implementations like a state pattern? – Larry Mar 26 '15 at 11:43
  • @Larry, Victor: Sorry for the delay. It takes me some time to think this through and look some things up. I tried to illustrate this with my `Driver` interface example. "State" is not so much of a problem since most of it is already encapsulated away in the caches and I could pass my "BasicCar" to the Delegate anyway. This is where my cars example reaches it's limits. (Simplified problem -> simple answer?) I guess what makes me dislike this idea the most is, that I have to rip my perfecly fine object apart in many small pieces. – Scheintod Mar 26 '15 at 12:03
  • In real world there are about 20 methods which need to be factored out in such a way. This would make it anything but clear. I still hope someone could come up with a better idea for something I could do more clearly in every crappy script language. – Scheintod Mar 26 '15 at 12:05
  • 1
    @Scheintod a gentle reminder, before you do the refactor dont forget to have unit tests to cover . – Larry Mar 26 '15 at 12:08
  • @Larry: thanks for the reminder. I have some there. But it's a great idea. Instead of brooding over this I could write some more :) – Scheintod Mar 26 '15 at 12:15
4

Split Functionality and State

If you have to do a big refactoring anyway - a good way to tackle this complex problem would be to separate state and functionality. Just remember how Object-Methods in Java work behind the scenes: Essentially a object-function is a static function with the first argument being "this". The "this" parameter is a state-object with all the attributes you need. The functionality doesn't have to be bound to this.

It could look like this:

class CarState {
  public float fuel;
  public String name;
}

class BasicCarFunctionality {
  public static void accelerate( CarState car ) {
    System.out.println( "accelerating" );
  }
}

class SportscarFunctionality {
  public static void drive( CarState car, String how ) {
    // Here you can reference Basic-Behaviour if you want
    BasicCarFunctionality.accelerate( car );
    System.out.println( car.name + " drive " + how );
  }
}

class TruckFunctionality {
  public static void steer( CarState car, String how ) {
    System.out.println( car.name + " steer " + how );
  }
}

interface SportsCar {
  void doDrive( String how );
}

interface Truck {
  void doSteer( String how );
}

class Firewagon implements SportsCar, Truck {
  private CarState car = new CarState();

  @Override
  public void doDrive( String how ) {
    SportscarFunctionality.drive( car, how );
  }

  @Override
  public void doSteer( String how ) {
    TruckFunctionality.steer( car, how );
  }
}

If you need additional State-Attributes for your firewagon which you don't need in every Car, you can compose your state with a new State object:

class FirewagonExtraState {
  public float waterAmount;
  public boolean sirenActive;
}

// And ammend the Firewagon Class:
class Firewagon implements SportsCar, Truck {
  private CarState car                  = new CarState();
  private FirewagonExtraState firewagon = new FirewagonExtraState();

  @Override
  public void doDrive( String how ) {
    FirewagonFunctionality.activateHorn( firewagon );
    SportscarFunctionality.drive( car, how );
  }

  @Override
  public void doSteer( String how ) {
    TruckFunctionality.steer( car, how );
  }
}
Falco
  • 3,287
  • 23
  • 26
  • And if you have multiple layers you can also add `BasicCarFunctionality` with static Methods for the BasicCar functions. And you can call all of these functions from any other function, passing the same CarState. And if you need additional state attributes, you can create a composite State object, consisting of a CarState and an "FiretruckExtraState" with additional attributes – Falco Mar 26 '15 at 13:00
  • Hi Falco, thanks for your answer and thank you for reminding me of this variant of `Delegate` pattern. I think we now have them complete. (Is this even possible?). The main difference to my `Delegate` example is, that the the real functionality is not stored in the implementation of a FunctionalInterface but in a static method. (Sometimes this is more clear, sometimes it contradicts oo. sometimes both :) ) – Scheintod Mar 26 '15 at 13:28
  • The funny thing is, I already have (most of) the state separated in the DAO object for which my imaginary `BasicCar` object is the `Facade` (accessor). (one could call it "DatabaseCar" or so.) – Scheintod Mar 26 '15 at 13:29
2

I'm not sure the analogy is correct enough to give you a good answer..

The most basic way to deal with multiple inheritance issues in Java is to use interfaces and then delegate behavior using composition.

Cars and trucks both have steering and acceleration, but a truck isn't a car, and shouldn't inherit behavior from it just because some of the implementation is shared. Pull the shared implementation out to a class that makes more sense (Steering column, drive train, whatever), and then delegate to it from both the car and the truck.

Using a functional interface makes this less cumbersome, but you don't need Java 8 to solve the problem.

1

What about this:

public class SportsCar implements Car {
    private final BasicCar basicCar;
    public SportsCar( String name ) {
        this.basicCar = new BasicCar(name);
    }

    public SportsCar( BasicCar basicCar ) {
        this.basicCar = basicCar;
    }

    @Override
    public String accelerate() {
        return basicCar.accelerate() + " fastly";
    }
    @Override
    public String decelerate() {
        return basicCar.decelerate() + " fastly";
    }

    @Override
    public String steerLeft(){
        return basicCar.steerLeft() + " fastly";
    }

    @Override
    public String steerRight(){
        return basicCar.steerLeft() + " fastly";
    };
}

public class Truck implements Car {
    private final BasicCar basicCar;

    public Truck( String name ) {
        this.basicCar = new BasicCar(name);
    }

    public Truck( BasicCar basicCar ) {
        this.basicCar = basicCar;
    }

    @Override
    public String accelerate() {
        return basicCar.accelerate() + " carefully";
    }
    @Override
    public String decelerate() {
        return basicCar.decelerate() + " carefully";
    }

    @Override
    public String steerLeft(){
        return basicCar.steerLeft() + " carefully";
    }

    @Override
    public String steerRight(){
        return basicCar.steerLeft() + " carefully";
    };
}

Now for the FireTruck class

public class FireTruck implements Car {
    Collection<Car> behaviors;
    BasicCar basicCar;

    public FireTruck(String name ) {
        this.behaviors = new ArrayList<String>();

        this.basicCar = new BasicCar(name);

        this.behaviors.Add(new SportsCar(this.basicCar));
        this.behaviors.Add(new Truck(this.basicCar));
    }

    @Override
    public String accelerate() {
        StringBuilder result = new StringBuilder();

        for(Car c : behaviors){
            result.append(c.accelerate());
        }

        //and if I wanted to do my own thing here as a 'FireTruck' I could, something like :
        String myOwnAction = basicCar.accelerate() + " sounding alarms and flashing red light";
        result.append(myOwnAction);
    }
    //same for other methods : decelerate, steerLeft and steerRight
}
snajahi
  • 900
  • 2
  • 14
  • 26
  • Hi snajahi, thanks for your answer. Like I wrote in my question I absolutely need the `doSteer` and `doDrive` methods since the real work (read: much code) is done there. The problem arises because I don't like to copy/paste the `doSteerLeft`-like methods in the descendants. But you're right: If this wasn't the case there wouldn't be a problem. – Scheintod Mar 26 '15 at 12:10
  • This code does indeed suppose that the `doStear` and `doDrive` methods _are_ present, but only in the `BasicCar` class, are you stating that they _have_ to be present in `SportsCar` and `Truck` classes as well? – snajahi Mar 26 '15 at 12:18
  • snajahi: sorry. I didn't read your code correctly. But the problem remains: I need to override the `do...` methods because I have to change there basic functionality. Pretty hard to explain in just a vew lines: It's something like: `doDrive(){ getPropertyA(); do_stuff() }` will be overwritten with: `doDrive(){ getPropertyB(); do_stuff() }'. (it has something to do with articles which can contain other articles which in turn change containing articles's behaviour.) – Scheintod Mar 26 '15 at 13:03
0

I asked a very similar question some time ago... maybe you'll find it useful:

A Collection of an Abstract Class (or something like that...)

Community
  • 1
  • 1
Peter
  • 4,021
  • 5
  • 37
  • 58