代码之家  ›  专栏  ›  技术社区  ›  matoni

通知超类创建子类

  •  2
  • matoni  · 技术社区  · 7 年前

    有没有办法自动将通知从子类发送到超类 子类完全初始化后 i、 e.完成子类构造函数后?

    动机

    基类必须提供一些处理类字段列表的默认方法。由于子类字段只有在创建子类之后才能在父类中访问,所以基类不能在基类构造函数中读取这些子类字段。一种解决方案是在需要处理这些字段的每个基本方法的开头读取子类字段。由于反射速度慢,最好使用延迟初始化。

    我很好奇是否有 不广为人知的回调机制 在Java中,这将允许定义一些“子类创建的回调”,以便我能够初始化这些字段,而无需使用延迟初始化来实现 更好的可维护性 .

    我知道可以跟踪对象的释放,例如通过 finalize() ReferenceQueue 所以我想知道是否有类似的东西用于对象创建。

    例子

    假设要创建数据库 Entity 类(我知道有基于ORM的解决方案,但这只是为了说明类似的问题),它将能够根据实体的类字段生成SQL语句,如CREATE TABLE、INSERT、UPDATE、DELETE。所以基类将负责读取类字段并生成这些语句。要创建实体,只需扩展 实体 并使用一些字段注释,如 @Column , @Id , @AutoIncrement , ...

    class Entity {
        public String getCreateTableStatement() {
            // lazy-initialize list of class fields and produce statement...
        }
    
        public String getInsertPreparedStatement() {
            // lazy-initialize list of class fields and produce statement...
        }
    
        // update, delete, ...
    }
    

    子类示例

    public Person extends Entity {
        @Id public int id;
        @Column public String name;
    }
    

    目标

    替换延迟初始化的另一种模式将有助于减少重复代码的数量。理想情况下,子类不必定义任何其他内容,只需“ extends Entity ".

    2 回复  |  直到 7 年前
        1
  •  2
  •   Mick Mnemonic    7 年前

    有点不清楚您想做什么,但一般来说,许多与对象创建相关的问题都可以通过使用 factory method 这封装了创作过程。通过这种方式,您可以完成比单个构造函数调用所能实现的更多的工作:

    public static MySubClass createSubClass() {
        MySubClass subClass = new MySubClass();
        subClass.baseClassMethodThatManipulatesFields();
        return subClass;
    }
    

    请注意(正如其他人指出的那样),继承可能不是解决问题的最佳解决方案。列出的方法 Entity 应该由使用反射初始化类的工厂负责。

        2
  •  0
  •   Oleg Cherednik    7 年前

    我不是在问为什么。若您想完全像您的答案中所做的那个样,那个么父对象可以通过构造函数完全访问它的子对象。是的,我知道此时子对象尚未完全初始化,但在这一步中可以使用注释信息。

    这是一个例子:

    import org.apache.commons.lang3.reflect.MethodUtils;
    
    import javax.persistence.Id;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.AccessibleObject;
    import java.util.ArrayList;
    import java.util.List;
    
        public class Entity {
            protected Entity() {
                List<AccessibleObject> ids = getAccessibleObjectWithAnnotation(Id.class);
                List<AccessibleObject> columns = getAccessibleObjectWithAnnotation(Column.class);
            }
    
            private List<AccessibleObject> getAccessibleObjectWithAnnotation(Class<? extends Annotation> cls) {
                List<AccessibleObject> res = new ArrayList<>();
                res.addAll(FieldUtils.getFieldsListWithAnnotation(getClass(), cls));
                res.addAll(MethodUtils.getMethodsListWithAnnotation(getClass(), cls));
                return res;
            }
        }