【问题标题】:Call constructor in an abstract class在抽象类中调用构造函数
【发布时间】:2014-08-09 15:32:30
【问题描述】:

是否可以在抽象类中调用构造函数?

我读到这个构造函数可以通过它的非抽象子类之一来调用。但我不明白这种说法。谁能举个例子解释一下?

【问题讨论】:

  • Abstract classesincomplete 类,所以你不能调用它的构造函数,就像你不能开车没有车轮或引擎。
  • @Andremoniy 您可以调用抽象类的构造函数,但不能使用“普通”new _____() 表示法。
  • @Burkhard 类似的问题,但它没有解决 OP 在这里问的问题。
  • 注意:“是否可以在抽象类中调用构造函数?”这个问题可以用一段简单的代码来回答。不知道为什么你在问这个问题之前没有测试它。第二段是另一回事,我们很乐意向您解释。

标签: java oop constructor abstract-class


【解决方案1】:

Abstract 和 Concrete 类类似于 Java 中的 Generalization 和 Specialization,可以使用继承来执行。让我用一个简单明了的例子来解释。假设我们有一个类“DBConnector”。它似乎是更通用的类,实例化类的意义较小(您要连接到哪个数据库,驱动程序因每个数据库而异)。因此,我们可以将 DBConnector 设为抽象。这就是我们基本上不能实例化抽象类的原因。 现在我们可以为每个数据库创建不同的具体类,扩展我们具体类的行为,如“OracelDBConnector”、“MySQLDBConnector”等,当我们将抽象类的属性继承到具体类中时,我们理想地使用抽象类初始化抽象类属性使用超级(参数列表)的具体类构造函数。

谢谢, JK

【讨论】:

    【解决方案2】:

    你显然可以这样做:

    public class ConcreteClass extends AbstractClass {
        public ConcreteClass(){ // concrete class constructor
            super(); // abstract class constructor
        }
    }
    

    抽象类的构造函数只能在继承自它的具体类的构造函数中使用。

    【讨论】:

      【解决方案3】:

      在这个示例 Java 程序中,我们有一个抽象类 Servidor,它有一个参数构造函数,它接受名称。子类在创建 Servidor 的具体实例并覆盖抽象方法 start() 时为超类提供该名称。由于这个程序编译和运行良好,你可以肯定地说抽象类在 Java 中可以有构造函数。

      公共类 AbstractConstructorTest {

      public static void main(String args[]) {
         Servidor Servidor = new Tomcat("Apache Tomcat");
         Servidor.start();
      }
      

      }

      抽象类服务器{ 受保护的最终字符串名称;

      public Servidor(String name){
          this.name = name;
      }
      
      public abstract boolean start();
      

      }

      类 Tomcat 扩展了 Servidor{

      public Tomcat(String name){
          super(name);
      }
      
      @Override
      public boolean start() {
         System.out.println( this.name + " started successfully");
         return true;
      }
      

      }

      输出: Apache Tomcat 启动成功

      【讨论】:

        【解决方案4】:

        你不能用类实例创建表达式调用抽象类构造函数,即

        // Invalid
        AbstractClass x = new AbstractClass(...);
        

        但是,在构造对象时,您总是要通过整个继承层次结构的构造函数。因此子类的构造函数可以使用super(...) 调用其抽象超类的构造函数。例如:

        public class Abstract {
            protected Abstract(int x) {
            }
        }
        
        public class Concrete {
            public Concrete(int x, int y) {
                super(x); // Call the superclass constructor
            }
        }
        

        由于抽象类的构造函数只能在子类构造函数中调用(并且通过在同一个类中相互链接),我通常将它们设为protected...将它们设为public毫无用处。

        如果您未在具体子类构造函数中指定 super(...)this(...) 调用,则适用常规规则 - 它等效于构造函数开头的 super(); 语句,在超类中调用无参数构造函数...所以必须成为这样的构造函数。

        【讨论】:

          【解决方案5】:

          您可以在抽象类中定义构造函数,但不能构造该对象。但是,具体的子类可以(并且必须)调用抽象父类中定义的构造函数之一。

          考虑以下代码示例:

          public abstract class Test {
          
              // abstract class constructor
              public Test() {
                  System.out.println("foo");
              }
          
              // concrete sub class
              public static class SubTest extends Test {    
                // no constructor defined, but implicitly calls no-arg constructor 
                // from parent class
              }
          
              public static void main(String[] args) throws Exception {
                  Test foo = new Test(); // Not allowed (compiler error)
                  SubTest bar = new SubTest(); // allowed, prints "foo"
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-09-26
            • 1970-01-01
            • 2012-01-14
            • 2017-08-16
            • 2015-08-29
            • 2011-03-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多