在Java中扩展类并使用扩展类的实例进行构造

时间:2010-07-28 15:15:42

标签: java extend

我想扩展一个类,然后从已扩展的类的实例中复制该值,因此我在新类中获取所有参数。如果这没有意义,那就是我正在尝试做的一个简单例子:

public class MyTableModel extends DefaultTableModel {

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

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

这可能实现吗?

3 个答案:

答案 0 :(得分:3)

看起来你想要组合而不是继承。特别是,您似乎正在尝试使用decorator pattern。也就是说,您希望获取DefaultTableModel的现有实例,并创建另一个DefaultTableModel,将大多数方法转发给基础委托,但可能会添加/修改/修饰某些功能。

您永远不能设置this = somethingElse;,但您可以拥有DefaultTableModel delegate,并将大多数/所有请求转发给delegate,也许可以根据需要添加/装饰某些方法。

另见

  • Effective Java 2nd Edition,Item 16:赞成组合而不是继承

番石榴示例:ForwardingCollection

此模式的一个示例是ForwardingCollection from Guava

  

一个java.util.Collection,它将所有方法调用转发给另一个集合。子类应该重写一个或多个方法,以根据装饰器模式修改后端集合的行为。

您可以看到the source code以了解此模式的实施方式:

  @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...

正如您所看到的,只有将所有方法转发到ForwardingCollection,另一个implements Collectiondelegate()所做的只是Collection。可以理解这是一个相当重复和平凡的代码,但现在子类只能extends ForwardingCollection,只能装饰他们想要装饰的东西。

答案 1 :(得分:1)

您不能将Java中的 this 设置为任何内容,它只用于(this == someObject)之类的表达式或访问当前使用的对象的某些属性,如(this.someProperty)或者在构造函数内部初始化当前对象。有关this关键字

的详情,请参阅here

此代码可能会抛出java.lang.ClassCastException

MyTableModelDefaultTableModel,但DefaultTableModel不是MyTableModel。有关java中类型转换的更多详细信息,请参阅http://java.sun.com/docs/books/jls/third_edition/html/conversions.html

如果您希望从子类中的父类重用某些状态和/或行为,则应考虑将这些成员标记为protected,或考虑其他形式的组合。

答案 2 :(得分:0)

更好的方法是创建超类protected而不是private的字段 - 这将使您可以在子类中访问它们。

请注意,当您定义子类构造函数时,您还需要从超类中调用构造函数,因此在这方面您仍然可以传入所有必需的变量。

不要忘记,超类中的所有公共方法都可以被任何具有子类实例的代码调用。

编辑:一个小例子可能会有所帮助:

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();
        }
    }
}

如果我误解了您的要求,请告诉我,但听起来您想要访问超类的字段和行为 - 只要它们不是{{1,您就可以自动访问子类中的字段和行为}}