抽象类的公共构造函数是否有充分的理由

Are there good reasons for a public constructor of an abstract class

提问人:Raedwald 提问时间:1/25/2011 最后编辑:CommunityRaedwald 更新时间:4/2/2020 访问量:10451

问:

无法通过直接调用类的构造函数来创建对象。类的构造函数只能从派生类调用。因此,在我看来,抽象类的构造函数必须是包私有的或包私有的(后者用于将构造函数的使用限制为包中的派生类的不寻常情况)。然而,Java 允许类的构造函数是 .abstractabstractprotectedabstractpublic

在哪些情况下,将类的构造函数声明为 ,而不是 或 package-private 是有用的abstractpublicprotected

这与“抽象类构造函数访问修饰符”的问题并不完全重复:显然,您可以声明构造函数为 ;我想知道是否有任何充分的理由这样做。在我看来,没有。我看到 C# 具有类似的特性public

Java 构造函数 abstract-class

评论

0赞 Sandeep Jindal 6/29/2013
构造函数与对象的“创建”无关。它只是在“创建”对象时调用的方法。因此,抽象类可以具有公共构造函数,这些构造函数将在创建抽象类的实例(通过子类)时调用,并且在该构造函数方法中,您将编写代码来初始化成员变量。stackoverflow.com/questions/260666/......
1赞 Brian McCutchon 3/12/2014
构造函数也可以是 ,它可以在构造函数链接中使用。private
0赞 8protons 10/9/2019
抽象类可以有构造函数吗?

答:

28赞 Andreas Dolk 1/25/2011 #1

对于java来说,答案是一样的:

没有理由为抽象类使用公共构造函数。我认为编译器不抱怨的原因很简单,他们只是没有花时间覆盖它,因为它是公开的还是受保护的并不重要。(来源)

不能从直接子类以外的任何内容调用抽象类的构造函数。

因此,为抽象类构造函数的访问修饰符添加特殊规则不会为语言添加有用的东西。


一件事看起来像是这条规则的例外 - 如果抽象类只定义一个默认构造函数,那么子类就不必实现构造函数:这是合法的:

public abstract class A {
  public A() {}
}

public class B extends A {}

因此,我们可以通过调用来创建一个 - 但请注意,我们仍然创建一个而不是一个 .而且,同样,构造函数是公共的还是受保护的并不重要。它不应该是私有的,但编译器会注意到并抱怨......Bnew B()BAA

实际上,我们调用了一个“不可见”的公共默认构造函数,在该构造函数上执行简单的调用......Bsuper()

-10赞 Catalin Marin 1/25/2011 #2

如果未在子类的构造函数中定义,则可以具有公共构造函数。 例

abstract class Animal {
   String name;
   public void Animal(String name) {
         this.name = name;
   }
}


class Cat extends Animal{
    public String sayMayName() {
       return this.name;
    }
}

myCat = new Cat("tester");

name = myCat.sayMyName();

如果未定义构造函数,则将调用父类构造函数,如果它不是公共的,则将不起作用。我认为这在工厂模式中更优雅地完成,但我在 PHP 中在实践中使用它并且工作正常。

评论

5赞 Joachim Sauer 1/25/2011
这在 Java 中不起作用。此外,您没有在类中定义构造函数,因为您指定了返回类型 ()。Animalvoid
4赞 Andreas Dolk 1/25/2011
这不会编译 - 构造函数是必需的,因为有一个(非默认)构造函数(无论如何都不是造函数)CatAnimalpublic void Animal(String name)
0赞 biziclop 1/25/2011
这仅适用于无参数构造函数。试试吧,你的代码不会编译。但是,隐式默认构造函数将始终具有类本身的可见性,而不管超类构造函数是什么。
0赞 Catalin Marin 1/25/2011
我认为它可能在 java 中不起作用,这就是为什么我指定我在 PHP 中使用它(在那里你可以做任何“聪明”的想法)。
6赞 Kenny Cason 4/2/2013
-1,这也不是有效的PHP语法,问题被标记为Java
-7赞 foo 3/29/2014 #3

称我为异教徒,但是......我看到抽象类中构造函数至少有一种用途。

即:指定构造函数参数的样子。

指定一个抽象构造函数(从而使类抽象)。派生类必须使用其特定签名实现此构造函数才能失去抽象状态。

我没有看到其他方法可以指定强制性构造函数签名(如果您这样做,请帮助我)。

评论

3赞 Raedwald 3/29/2014
创建构造函数仍然允许您“指定构造函数参数的外观”。protected
0赞 foo 4/1/2014
true,但这样做需要派生类调用 super(),否则可能会丢失可能发生的 init 步骤。摘要阐明这只是签名,没有实现。- 最好允许接口指定构造函数签名。但是由于它们没有,我认为抽象类是下一个最好的东西。
3赞 Raedwald 4/1/2014
你不能避免打电话.如果不显式调用它,则隐式调用它。super
0赞 foo 3/15/2016
重点不是避免调用,关键是指定构造函数签名。super
0赞 Sean Van Gorder 6/27/2016
澄清一下,这个想法甚至行不通。 不是构造函数的合法修饰符,您可以通过修改类声明来使类抽象。Java 中没有办法强制要求子类的构造函数签名,它们永远不会被继承。abstract
0赞 wjs 2/5/2018 #4

可见性也会影响 javadoc 中显示的内容(如果选择它以排除某些可见性级别)。否则没关系,这可能是抽象类的公共构造函数的用法。

如果未提供构造函数,则默认构造函数为 public(如果类是 public)。最简单的选择是允许这样做,而不是强制受保护的构造函数。

从这个意义上说,相反的问题可以清楚地表明:为什么他们不在抽象类中强制使用受保护的构造函数?因为公共构造函数不会改变任何东西,所以它只会花费时间并增加复杂性。