Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple inheritance design issue in Java

How do you deal with having only single inheritance in java? Here is my specific problem:

I have three (simplified) classes:

public abstract class AbstractWord{
    String kind;    // eg noun, verb, etc

    public String getKind(){ return kind; }

}

public class Word extends AbstractWord{
    public final String word;

    ctor...

    public void setKind(){
        // based on the variable word calculate kind..
    }
}

public class WordDescriptor extends AbstractWord{

    ctor..

    public void setKind(String kind){this.kind = kind;}

}

This is what I consider my most basic implementation but I want to make other implementations.

Lets say that I want to add a new variable say wordLength but I want to add it using inheritance. Meaning I do NOT want modify that original AbstractWord class. Ie something along the lines of this:

public class Length{
    private int length;

    public int getLength(){return length};
}

public class BetterWord extends AbstractWord AND Length{

    public void setLength(){
        // based on the variable word calculate Length..
    }
}

public class BetterWordDescriptor extends AbstractWord AND length{

    public void setLength(int length){this.length = length;}
}

I know that java does not let me do this but it has made my code very ugly. Right now whenever I add a field I am just adding it to AbstractWord but then I either need to rename that AbstractWord (and Word and WordDescriptor). (I can't just add the field to the other one because of backwards compatibility, it break equals methods and stuff like that).

This seems like a pretty common design issue but I have racked my head and I cannot come up with any beautiful solutions.

Is there a design pattern that addresses this? I have some potential solutions but I wanted to see if there was something that I was missing.

thanks, Jake

Update: Length refers to the number of syllables in the word (sorry about the lack of clarity)

like image 558
sixtyfootersdude Avatar asked Jan 26 '10 22:01

sixtyfootersdude


People also ask

What is the problem with multiple inheritance in Java?

Java doesn't support multiple inheritances in classes because it can lead to diamond problem and rather than providing some complex way to solve it, there are better ways through which we can achieve the same result as multiple inheritances.

What is the problem with multiple inheritance?

Multiple inheritance has been a controversial issue for many years, with opponents pointing to its increased complexity and ambiguity in situations such as the "diamond problem", where it may be ambiguous as to which parent class a particular feature is inherited from if more than one parent class implements said ...

What are the patterns of multiple inheritance design?

Explanation: Adapter and observer patterns benefit from the multiple inheritances.


2 Answers

Favor composition over inheritance.

Solution takes into consideration that there could be another type of word that may need WordLengthSupport.

Similarly other interfaces could be created and implemented and various word types can have mix and match of those interfaces.

.

public class WordLength {
    private int length = 0;
    public int getLength(){return length};
    public void setLength(int length){this.length = length};
}

.

public interface WordLengthSupport {
    public WordLength getWordLength();
}

.

public class BetterWord extends AbstractWord 
        implements WordLengthSupport {
    WordLength wordLength;
    public WordLength getWordLength() {
        if(wordLength==null) {
            // each time word changes 
            // make sure to set wordLength to null
            calculateWordLength(); 
        }
        return wordLength;
    }
    private void calculateWordLength() {
        // This method should be 
        //    called in constructor 
        //    or each time word changes 
        int length = // based on the variable word calculate Length..
        this.wordLength = new WordLength();
        this.wordLength.setLength(length);
    }
}

.

public class BetterWordDescriptor extends AbstractWord  
        implements WordLengthSupport {
    WordLength wordLength;
    public WordLength getWordLength(return wordLength);
    public void setWordLength(WordLength wordLength) {
        // Use this to populate WordLength of respective word
        this.wordLength = wordLength;
    }
}

.

The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

This solution does not use strategy pattern but can be refactored for same.

like image 148
Gladwin Burboz Avatar answered Sep 22 '22 00:09

Gladwin Burboz


Just use composition instead of inheritance:

a BetterWord is-an AbstractWord that has-a Length:

public class BetterWord extends AbstractWord {

    private Length length;

    public void setLength(int value){
        length.setLength(value);
    }
}

EDIT

If the API needs an object of type Length, just add a getter:

public class BetterWord extends AbstractWord {

    private Length length;

    public void setLength(int value){
        length.setLength(value);
    }

    public Length getLength() {
        return length
    }
}

Or rename the implementation Length to LengthImpl and define an interface Length, because a class can implement multiple interfaces.

like image 31
Andreas Dolk Avatar answered Sep 19 '22 00:09

Andreas Dolk