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)
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.
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 ...
Explanation: Adapter and observer patterns benefit from the multiple inheritances.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With