How do you deal with having only single inheritance in java? Here is my specific problem:
I have three (simplified) classes:
public abstract class A
(I can't just add the field to the other one because of backwards compatibility, it break equals methods and stuff like that).
It won't break source compatibility. Not unless you're doing something really crazy in your equals methods.
And renaming your classes is generally not the way to handle binary compatibility.
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.
The problem is not "how to deal with single inheritance". What you're missing is not really a design pattern but learning to design the API separately from the implementation.
I would implement it like so:
public interface WordDescriptor {
void getKind();
Word getWord();
}
public interface Word {
String getWord();
}
public class SimpleWord implements Word {
private String word;
public SimpleWord(String word) { this.word = word; }
public String getWord() { return word; }
}
public class SimpleWordDescriptor implements WordDescriptor {
private Word word;
private String kind;
public SimpleWordDescriptor(Word word, String kind) {
this.word = word;
this.kind = kind; // even better if WordDescriptor can figure it out internally
}
public Word getWord() { return word; }
public String getKind() { return kind; }
}
With this basic setup, when you want to introduce a length property, all you have to do is this:
public interface LengthDescriptor {
int getLength();
}
public class BetterWordDescriptor extends SimpleWordDescriptor
implements LengthDescriptor {
public BetterWordDescriptor(Word word, String kind) {
super(word, kind);
}
public int getLength() { getWord().length(); }
}
The other answers that uses composition of properties as well as the Decorator pattern are also entirely valid solutions to your problem. You just need to identify what your objects are and how "composable" they are, and how they are to be used - hence designing the API first.
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.
With your specific example you could use the decorator pattern in conjunction with interfaces to supplement your Word
class with additional functionality; e.g.
// *Optional* interface, useful if we wish to reference Words along with
// other classes that support the concept of "length".
public interface Length {
int getLength();
}
// Decorator class that wraps another Word and provides additional
// functionality. Could add any additional fields here too.
public class WordExt extends AbstractWord implements Length {
private final Word word;
public class(Word word) {
this.word = word;
}
public int getLength() {
return word.getKind().length();
}
}
In addition it's worth noting that the lack of multiple inheritence in Java isn't really the issue here; it's more a case of reworking your design. In general it's considered bad practice to over-use inheritence as deep inheritence hierarchies are difficult to interpret / maintain.
/** * First example */
class FieldsOfClassA {
public int field1;
public char field2;
}
interface IClassA {
public FieldsOfClassA getFieldsA();
}
class CClassA implements IClassA {
private FieldsOfClassA fields;
@Override
public FieldsOfClassA getFieldsA() {
return fields;
}
}
/**
* seems ok for now
* but let's inherit this sht
*/
class FieldsOfClassB {
public int field3;
public char field4;
}
interface IClassB extends IClassA {
public FieldsOfClassA getFieldsA();
public FieldsOfClassB getFieldsB();
}
class CClassB implements IClassB {
private FieldsOfClassA fieldsA;
private FieldsOfClassB fieldsB;
@Override
public FieldsOfClassA getFieldsA() {
return fieldsA;
}
@Override
public FieldsOfClassB getFieldsB() {
return fieldsB;
}
}
/**
wow this monster got bigger
imagine that you will need 4 lvl of inheritance
it would take so much time to write this hell
I'm even not talking that user of those iface will think
what fields i will need fieldsA fieldsB fieldsC or another one
So composition does not work here and your pathetic tries are useless
When u think about Oject Oriented programming
u need BIG models with 6-7 lvls of multiple inheritance
because that is good test and because corresponds to models of real life or math models tested by civilization for 4 thousands years.
If your models require 2 lvl of inheritance stop pretending u using OO
U can easily implement it with any language even procedural one like C or Basic language */