构造函数重载 - Java 中的最佳实践 [已关闭]

构造函数也可以像任何其他方法一样重载,我知道这一事实。由于一个任务,我决定使用具有多个构造函数的抽象超类:

抽象超类:

protected ListSortierer()
{
  this( null, null );
}

protected ListSortierer( List<E> li )
{
  this( li, null );
}

protected ListSortierer( Comparator<E> comp )
{
  this( null, comp );     
}

protected ListSortierer( List<E> li, Comparator<E> com )
{
  this.original = Optional.ofNullable( li );
  this.comp = Optional.ofNullable( com );
}

要访问这些构造函数中的每一个,我还需要在子类中有多个构造函数。

气泡排序.java:

public ListBubbleSort()
{
  super();
}

public ListBubbleSort( List<E> li )
{
  super( li );
}

public ListBubbleSort( Comparator<E> com )
{
  super( com );
}

public ListBubbleSort( List<E> li, Comparator<E> com )
{
  super( li, com );
}

在这种情况下,子类的每个构造函数都会立即调用超类的构造函数。我想到我可以再次引用自己的构造函数并传递值:null

public ListBubbleSort()
{
  this( null, null );
}

public ListBubbleSort( List<E> li )
{
   this( li, null );
}

public ListBubbleSort( Comparator<E> com )
{
   this( null, com );
}

public ListBubbleSort( List<E> li, Comparator<E> com )
{
   super( li, com );
}

这样做可以让我省略抽象超类中的3个重载构造函数,但会强制每个子类都遵循相同的模式。

我的问题是:在一致性的情况下,更好的方法是什么?处理抽象超类或子类中的缺失值?它对实例化有影响,还是只是一个意见问题?


答案 1

在一致性的情况下,什么是更好的方法?

  1. 将所有子构造函数设为私有。
  2. 引入静态工厂方法。

    ListBubbleSort.withList(List<E> list)
    ListBubbleSort.withComparator(Comparator<E> comparator)
    
  3. 调用正确的构造函数。不要传递任何 s。supernull

    public static <E> ListBubbleSort withList(List<E> list) {
        return new ListBubbleSort(list);
    }
    
    private ListBubbleSort(List<E>) {
        super(list);
    }
    
    protected ListSortierer(List<E>) {
        // initialise only the list field
        this.origin = list;
    }
    
  4. 不要将“可选”用作字段。

    this.original = Optional.ofNullable(li);

  5. 如果您有 3 个以上的参数,请考虑生成器模式

处理抽象超类或子类中的缺失值?

构造函数应该提供初始值。您没有传递初始值,只是指示它们不存在

默认情况下,是引用类型的初始值。因此,如果尚未给出字段的值,则无需重新分配字段。null

它对实例化有影响,还是只是一个意见问题?

可读性,维护。


我建议阅读Joshua Bloch的《Effective Java》

创建和销毁对象

  • 项目 1:考虑静态工厂方法而不是构造函数
  • 项目 2:在面对许多构造函数参数时考虑构建器

答案 2

关于问题本身:我认为这两种选择都不理想。

你努力写尽可能少的代码。您小心添加重载,因为它们看起来很方便。实际上,你应该反其道而行之:非常认真地思考你真正的用例是什么,并且只支持这些用例。

在你的例子中,练习的全部意义似乎是允许使用不同的实现进行排序。从这个意义上说,你应该研究策略模式

换句话说:你的第一个想法总是更喜欢组合而不是继承。当你的设计把你引向这样的问题时,更好的答案可能是从你当前的设计中退后一步,找到一种方法来启用不同的排序作为某种“服务”——而不是将列表本身备份成一个排序的东西。


推荐