tags:

views:

82

answers:

4

I would like to extend a class and then copy the value from an instance of the class which has been extended, so I get all its parameters in my new class. In case this doesn't make sense, a simple example of what I'm trying to do:

public class MyTableModel extends DefaultTableModel {

    public MyTableModel(DefaultTableModel model){
        this = (MyTableModel) model; /* I realise this is invalid */
    }

    public newMethod(){
        // Some additional code
    }
}

Is this possible to achieve?

A: 

A better way to do this would be to make the fields of the superclass protected instead of private - this will give you access to them in your subclass.

Note that when you defined the subclass constructor, you will need to call a constructor from the superclass as well, so in that respect you'll still be able to pass in all the required variables.

And don't forget that all public methods in the superclass can be called as-is by any code that has an instance of your subclass.

EDIT: A little example might help:

public class DefaultTableModel
{
    protected String modelName;
    protected int numberOfTables;
    private numTimesReinited = 0;

    public DefaultTableModel(String name, int numTabs)
    {
        modelName = name;
        numberOfTables = numTabs;
    }

    public void reinit()
    {
        numTimesReinited++;
        // Other stuff
    }

    protected int getNumberOfReinits()
    {
        return numTimesReinited;
    }

    public String getName()
    { 
        return name;
    }
}

 

public class MyTableModel extends DefaultTableModel
{
    private String modelType;

    public MyTableModel(String name, int numTables, String modelType)
    { 
        super(name, numTables); // sets up the fields in the superclass
        this.modelType = modelType;
    }

    // purely "local" code
    public void getModelType()
    {
        return modelType;
    }

    // Accesses several protected data to provide new (public) functionality
    public void addTable()
    {
        if (getNumberOfReinits() < 10)
        {
           numberOfTables++;
           reinit();
        }
    }
}

Let me know if I've misunderstood your requirements, but it sounds like you want to access fields and behaviour of the superclass - which you'll have automatic access to in your subclass so long as they're not private.

Andrzej Doyle
I don't think that will work here - seems the OP has an existing object and may not necessarily have had the ability to instantiate that object as a MyTableModel in the first instance.
Dan
Ah, I think you might be right. When I read the question, it started with "I want to extend a class" so I took that as the fundamental requirement. On reflection I think that other answers are likely correct, and the Decorator pattern is the most suitable answer.
Andrzej Doyle
+3  A: 

It looks like you want composition instead of inheritance. In particular, it looks like you're trying to use the decorator pattern. That is, you want to take an existing instance of DefaultTableModel, and create another DefaultTableModel that forwards most of the methods to the underlying delegate, but perhaps adding/modifying/decorating some functionalities.

You can never set this = somethingElse;, but you can have a DefaultTableModel delegate, and forward most/all requests to delegate, perhaps adding/decorating some methods as necessary.

See also

  • Effective Java 2nd Edition, Item 16: Favor composition over inheritance

Guava Example: ForwardingCollection

An example of this pattern is ForwardingCollection from Guava:

A java.util.Collection which forwards all its method calls to another collection. Subclasses should override one or more methods to modify the behavior of the backing collection as desired per the decorator pattern.

You can see the source code to see how this pattern is typically implemented:

  @Override protected abstract Collection<E> delegate();

  public int size() {
    return delegate().size();
  }    
  public boolean isEmpty() {
    return delegate().isEmpty();
  }
  public boolean removeAll(Collection<?> collection) {
    return delegate().removeAll(collection);
  }
  // many more interface Collection methods implemented like above...

As you can see, all the ForwardingCollection does is it implements Collection simply by forwarding all methods to its delegate(), another Collection. Understandably this is rather repetitive and mundane code to write, but now subclasses can simply extends ForwardingCollection and only decorate what they want to decorate.

polygenelubricants
+1  A: 

Is your idea something like the Delegation Pattern?

keuleJ
A: 

You can't not set this in Java to anything, it is just used for expressions like (this == someObject) or accessing some property of the object being currently used like (this.someProperty) or inside a constructor to initialize the current object. See here for more info about the this keyword

This code will likely throw a java.lang.ClassCastException

That is MyTableModel is a DefaultTableModel but DefaultTableModel is not a MyTableModel. See http://java.sun.com/docs/books/jls/third_edition/html/conversions.html for more details about type conversion in java

If there is some state and/or behavior that you want to reuse from your parent class in your subclass you should consider marking those members as protected, or consider other form of composition.

StudiousJoseph