【问题标题】:Extending class in Java and constructing using an instance of the extended class在 Java 中扩展类并使用扩展类的实例进行构造
【发布时间】:2011-03-22 05:25:01
【问题描述】:

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

public class MyTableModel extends DefaultTableModel {

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

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

这有可能实现吗?

【问题讨论】:

    标签: java extend


    【解决方案1】:

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

    您永远不能设置this = somethingElse;,但您可以拥有DefaultTableModel delegate,并将大部分/所有请求转发到delegate,可能会根据需要添加/装饰一些方法。

    另见

    • Effective Java 第 2 版,第 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 Collection,只需将所有方法转发给它的delegate(),另一个Collection。可以理解,这是相当重复和平凡的代码编写,但现在子类可以简单地 extends ForwardingCollection 并且只装饰他们想要装饰的东西。

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

        【解决方案3】:

        一个更好的方法是使超类的字段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();
                }
            }
        }
        

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

        【讨论】:

        • 我认为这在这里行不通 - 似乎 OP 有一个现有对象,并且可能不一定有能力在第一个实例中将该对象实例化为 MyTableModel。
        • 啊,我想你可能是对的。当我阅读这个问题时,它以“我想扩展一个类”开头,所以我把它作为基本要求。经过反思,我认为其他答案可能是正确的,而装饰器模式是最合适的答案。
        猜你喜欢
        • 2023-03-26
        • 1970-01-01
        • 1970-01-01
        • 2013-11-15
        • 2016-12-28
        • 2021-02-13
        • 2010-12-14
        • 2021-12-13
        • 2012-12-10
        相关资源
        最近更新 更多