关于java:抽象类中的构造函数?

Constructors in abstract classes?

本问题已经有最佳答案,请猛点这里访问。

为什么抽象类可以有一个构造函数?因为我们不能创建它的对象,为什么我们需要一个抽象类中的构造函数?


在某些情况下,我们需要初始化抽象类中的字段。如果它是一个空的构造函数,这是由子类中的构造函数隐式完成的,否则我们使用super(parameters)。带有参数的构造函数强制子类指定一些参数(不一定是来自它自己的参数)。

总之,这意味着构造函数由子类构造函数使用,而不是从"外部"使用。


通过向抽象类添加构造函数,可以强制子类调用super以初始化某些字段。例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<wyn>
abstract class Person {
   private String name;
   public Person(String name) {
      this.name = name;
   }
}

class SoccerPlayer extends Person {
   public SoccerPlayer(String name) {
     super(name);
   }
}
Person p = new SoccerPlayer("Ronaldo");
</wyn>


您仍然需要能够创建一个子类,该子类必须调用其父类的构造函数和其父类等。

真正的问题是,为什么可以将抽象类构造函数公开。;)


因为继承Abstract类的类可以调用此构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
abstract class Foo {

    private int number;

    public Foo(int i) {
        this.number = i;
    }
}

class Bar extends Foo {

    public Bar() {
        super(1);
    }

}

将抽象类想象为派生类的蓝图,最多1或2个方法必须在派生类中实现。在抽象类(包括构造函数)中尽可能多地/合理地实现是有意义的。


子类可以被实例化,并且可以从其构造函数调用抽象类的构造函数。例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
abstract class Foo
{
  public Foo()
  {
    // Do Stuff
  }
}

class Bar extends Foo
{
  public Bar()
  {
    super();
  }
}


基类中的构造函数可用于进行构造函数链接,例如,您可以初始化基类字段。在这个构造函数中,您可以放置一些业务逻辑来验证参数

施工链示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract class Person
{
    protected readonly string Name;

    protected Person(string name)
    {
        //Do some validations or regex on the name for example so you know all person names match your business rules
        Name = name;
    }
}

public class Employee : Person
{
    private decimal _salary;

    public Employee(string name, decimal salary)
        : base(name)
    {
         _salary = salary;
    }
}

抽象类表示更顶级的对象,在某些情况下,这些顶级对象需要在业务透视图创建对象时设置值。缺少设置此值可能会导致业务对象失败。抽象类中支持构造函数来强制在生成类时设置值(否则可能会被忘记)。例如,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract class AccountHolder
{
}

    public abstract class Account
    {
         private AccountHolder holder;

    public Account(AccountHolder holder)
    {
    this.holder = holder;
    }
    }

    public class FixedDeposit extends Account
    {
    public FixedDeposit (AccountHolder holder)
    {
    super(holder)
    }
    }

在这里,我们无法想象没有持有人的账户,因此在创建对象时设置持有人对业务至关重要。在基础级别设置它可以确保在添加新类型的子类时强制设置它。因此,它是确保"开放扩展,封闭修改"的坚实原则之一。


抽象构造函数强制从类继承的类实现(或调用)构造函数。这意味着您可以确保将执行抽象类的构造函数中的任何操作。