【问题标题】:Are there good reasons for a public constructor of an abstract class抽象类的公共构造函数是否有充分的理由
【发布时间】:2011-06-15 05:22:43
【问题描述】:

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

在任何情况下有用abstract 类的构造函数声明为public,而不是protected 或包私有?

这不是问题“Abstract class constructor access modifier”的完全重复:显然你可以将构造函数声明为public;我想知道是否有任何好的理由这样做。在我看来,没有。我看到了C# has a similar peculiarity

【问题讨论】:

  • 构造函数与对象的“创建”无关。它只是一种在“创建”对象时调用的方法。因此,抽象类可以具有在创建抽象类实例(通过子类)时调用的公共构造函数,并且在该构造函数方法中,您将编写代码来初始化成员变量。 stackoverflow.com/questions/260666/…
  • 构造函数也可以是private,可以在构造函数链中使用。

标签: java constructor abstract-class


【解决方案1】:

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

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

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

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


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

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

public class B extends A {}

所以我们可以通过调用new B() 创建一个B - 但请注意,我们仍然创建一个B 而不是A。同样,A 中的构造函数是公共的还是受保护的都没关系。它不应该是私有的,但编译器会注意到并抱怨......

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

【讨论】:

    【解决方案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 中使用它并且效果很好。

    【讨论】:

    • 这在 Java 中不起作用。此外,您没有在 Animal 类中定义构造函数,因为您指定了返回类型 (void)。
    • 这不会编译 - 在Cat需要构造函数,因为Animal 有一个(非默认)构造函数(public void Animal(String name) 无论如何都不是构造函数)
    • 这只适用于无参数构造函数。试试看,你的代码不会编译。但是隐式默认构造函数将始终具有类本身的可见性,无论超类构造函数是什么。
    • 我认为它在 java 中可能不起作用,这就是为什么我指定我在 PHP 中使用它(在那里你可以做任何“聪明”的想法)。
    • -1,这也不是有效的 PHP 语法,问题被标记为 Java
    【解决方案3】:

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

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

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

    我认为没有其他方法可以指定强制构造函数签名(如果你这样做了,请帮帮我)。

    【讨论】:

    • 使构造函数protected 仍然允许您“指定构造函数参数的样子”。
    • true,但这样做需要派生类调用 super() 否则可能会丢失可能发生的初始化步骤。摘要澄清这只是签名,没有实现。 - 最好允许接口指定构造函数签名。但既然他们不这样做,我认为抽象类是下一个最好的东西。
    • 您无法避免致电super。如果你没有显式调用它,它会被隐式调用。
    • 重点不是避免调用super,重点是指定构造函数签名。
    • 澄清一下,这个想法甚至行不通。 abstract 不是构造函数的合法修饰符,您可以通过修改类声明来使类抽象。 Java 中没有办法为子类强制使用构造函数签名,它们永远不会被继承。
    【解决方案4】:

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

    如果你没有提供构造函数,那么如果类是公共的,则默认构造函数是公共的。最简单的选择是允许这样做,而不是强制受保护的构造函数。

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

    【讨论】:

      猜你喜欢
      • 2011-02-14
      • 2010-12-13
      • 2014-05-18
      • 2013-08-29
      • 2014-12-23
      • 1970-01-01
      • 2011-05-30
      • 2013-11-17
      • 2010-11-24
      相关资源
      最近更新 更多