当前位置:  开发笔记 > 编程语言 > 正文

如何编写子类构造函数而不重复代码?

如何解决《如何编写子类构造函数而不重复代码?》经验,为你挑选了1个好方法。

我想generateId()在抽象超类的构造函数中调用抽象方法,其中此抽象方法依赖于相应子类的某些字段.为清楚起见,请考虑以下代码:

抽象类: SuperClass

public abstract class SuperClass {
   protected String id;

   public SuperClass() {
        generateId();
   }

   protected abstract void generateId();
}

子类: Sub1

public class Sub1 extends SuperClass {
   private SomeType fieldSub1;

   public Sub1(SomeType fieldSub1) {
      this.fieldSub1 = fieldSub1;
      super();
   }

   protected void generateId() {
      // Some operations that use fieldSub1
   }
}

子类: Sub2

public class Sub2 extends SuperClass {
   private SomeOtherType fieldSub2;

   public Sub2(SomeOtherType fieldSub2) {
      this.fieldSub2 = fieldSub2;
      super();
   }

   protected void generateId() {
      // Some operations that use fieldSub2
   }
}

但是,子类构造函数不起作用,因为它super();必须是构造函数中的第一个语句.

OTOH,如果我super();在子类的构造函数的第一条语句,那么我就不能打电话generateId()SuperClass.因为generateId()在子类中使用字段,这些字段必须在使用之前初始化.

在我看来,"解决"这个问题的唯一方法是:删除generateId()超类中的调用.generateId()每个子类的构造函数的末尾调用.但这会导致代码重复.

那么有没有办法解决这个问题而不重复我的代码?(也就是说,不调用每个子类generateId()的构造函数的末尾?)



1> ericbn..:

正如@GuillaumeDarmont指出的那样,在构造中使用可覆盖的方法是不好的做法.

您希望强制超类id由子类初始化,因此更改构造函数:

public abstract class SuperClass {
    protected String id;

    public SuperClass(String id) {
        this.id = id;
    }
}

此外,您可能希望更改generateId()为静态方法,因为this在调用超类构造函数之前无法引用:

public class Sub1 extends SuperClass {
    private SomeType fieldSub1;

    public Sub1(SomeType fieldSub1) {
        super(generateId(fieldSub1));
        this.fieldSub1 = fieldSub1;
    }

    private static String generateId(SomeType fieldSub1) {
        // Some operations that use fieldSub1
    }
}

编辑:由于SuperClass不知道如何计算id,但你想强制它有一个id,你的一个选项是上面的解决方案.另一种选择是:

public abstract class SuperClass {
    private String id;

    public String getId() {
        if (id == null) { id = generateId(); }
        return id;
    }
    protected abstract String generateId();
}


public class Sub1 extends SuperClass {
    private SomeType fieldSub1;

    public Sub1(SomeType fieldSub1) {
        this.fieldSub1 = fieldSub1;
    }

    @Override protected String generateId() {
        // Some operations that use fieldSub1
    }
}

两个解决方案之间的区别在于何时将计算id:在对象初始化时,或第一次请求id.这就是@Turing85正在讨论的内容.

推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有