BeneStr
BeneStr

Reputation: 347

Have a class be subclass for several super classes

There are several (5+) classes, in code I cannot change, that I need to extend by a few fields. Is there any way to do this without writing (and editing every time I need to change something) the almost exactly same code 5 times? So is there any more elegant way than this:

class Subclass1 extends Superclass1 {
    private String newField;    

    public String getNewField() {
        return newField;
    }

    public void setNewField(String newField) {
        this.newField = newField;
    }

}
class Subclass2 extends Superclass2 {
    private String newField;    

    public String getNewField() {
        return newField;
    }

    public void setNewField(String newField) {
        this.newField = newField;
    }

}
//...

I do NOT want multiple inheritance, I want 5 seperate subclasses - just without the duplicate code, because the subclasses all add exactly the same.

The only alternative I can think of is copying the original classes and having the copy extend a Superclass which is probably even worse.

Upvotes: 3

Views: 169

Answers (3)

Mike Baranczak
Mike Baranczak

Reputation: 8374

Since you can't change the base classes, it's impossible to eliminate the redundancy. Eric Galluzzo's idea to store the extra fields in a separate class is the best one so far, but I don't know if that's practical in your case. If it isn't, create an interface that defines the extra fields. You'll still have to do a lot of repetitive typing, but at least you'll know immediately when you've made a mistake.

Upvotes: 1

Eric Galluzzo
Eric Galluzzo

Reputation: 3241

No, you can't do this in Java. You can in certain other JVM-based languages, such as Scala (traits). However, if you must use plain Java, you might consider the following:

  • Determine the (hopefully single) purpose of the fields you are adding, and the behavior that you want.
  • Create a new class encompassing all of the fields and the new methods. For example:

    public class ExtraFields  // Don't use this name!
    {
        private String myExtraField1;
        private String myExtraField2;
        // etc.
    
        public void doSomethingWithExtraFields() {
            // etc.
        }
    }
    

Then, you could take one of the following approaches:

  1. Subclass each of the five classes, and add one field, which is an instance of the class you created above, and delegate behavior accordingly. You will have to use this approach if you must have the extra fields in places where you must pass in one of your five classes. For example:

    public class Subclass1 extends Superclass1
    {
        private ExtraFields extraFields;
    
        public MySubclass()
        {
            super();
            extraFields = new ExtraFields();
        }
    
        public void doSomethingWithExtraFields()
        {
            extraFields.doSomethingWithExtraFields();
        }
    }
    
  2. Create a new wrapper class that contains an instance of both your new class created above, and one of those five subclasses. You can make this typesafe using generics. For example:

    public class Wrapper<T>  // Don't use this name either...
    {
        private ExtraFields extraFields;
        private T myClass;
    
        public Wrapper(T myClass) {
            this.myClass = myClass;
            this.extraFields = new ExtraFields();
        }
    }
    

    In this second approach, you don't strictly need the ExtraFields class. But it's still often a good idea to do this so as to encapsulate related functionality.

Hope that helps!

Upvotes: 4

Cinnam
Cinnam

Reputation: 1922

You could use a generic wrapper class, as long as it wouldn't be too tedious to change the rest of the code that works with it.

class Wrapper<E> {

    private E obj;
    private String newField;

    public Wrapper (E obj) {
        this.obj = obj;
    }
    public E get() {
        return obj;
    }

    public String getNewField() {
        return newField;
    }
    public void setNewField(String newField) {
        this.newField = newField;
    }
}

Upvotes: 0

Related Questions