抽象类可以有构造函数吗?

时间:2008-11-04 02:46:22

标签: java constructor abstract-class

抽象类可以有构造函数吗?

如果是这样,它如何使用以及用于何种目的?

22 个答案:

答案 0 :(得分:598)

是的,抽象类可以有一个构造函数。考虑一下:

abstract class Product { 
    int multiplyBy;
    public Product( int multiplyBy ) {
        this.multiplyBy = multiplyBy;
    }

    public int mutiply(int val) {
       return multiplyBy * val;
    }
}

class TimesTwo extends Product {
    public TimesTwo() {
        super(2);
    }
}

class TimesWhat extends Product {
    public TimesWhat(int what) {
        super(what);
    }
}

超类Product是抽象的,并且有一个构造函数。具体类TimesTwo有一个构造函数,它只对值2进行硬编码。具体类TimesWhat有一个构造函数,允许调用者指定值。

抽象构造函数将经常用于强制类约束或不变量,例如设置类所需的最小字段。

  

注意:由于父级中没有默认(或无参数)构造函数   抽象类,子类中使用的构造函数必须显式调用   父构造函数。

答案 1 :(得分:149)

如果您处于以下某种情况,则可以在抽象类中定义构造函数:

  • 你想要表演一些 初始化(到的字段) 抽象类)之前 实际上实例化了一个子类 发生
  • 您已经定义了最终字段 抽象类,但你没有 在声明中初始化它们 本身;在这种情况下,你必须有 用于初始化这些的构造函数 字段

请注意:

  • 您可以定义多个 构造函数(具有不同的 参数)
  • 你可以(应该?)定义你的所有 构造者受到保护(制造它们 无论如何,公众毫无意义)
  • 你的子类构造函数可以 调用一个抽象的构造函数 类;它甚至可能必须调用它 (如果没有no-arg构造函数 在抽象类)

在任何情况下,不要忘记如果你没有定义构造函数,那么编译器会自动为你生成一个(这个是公共的,没有参数,什么也不做)。

答案 2 :(得分:55)

是的,它可以有一个构造函数,它的定义和行为就像任何其他类的构造函数一样。除了抽象类不能直接实例化,只能扩展,因此使用总是来自子类的构造函数。

答案 3 :(得分:34)

抽象类可以有构造函数

是的,当我们将一个类定义为一个抽象类时,它无法实例化,但这并不意味着一个Abstract类不能有一个构造函数。每个抽象类都必须有一个具体的子类,它将实现该抽象类的抽象方法。

当我们创建任何子类的对象时,相应的继承树中的所有构造函数都是从上到下的方法调用的。同样的情况适用于抽象类。虽然我们不能创建抽象类的对象,但是当我们创建一个类的对象时,它是抽象类的具体和子类,抽象类的构造函数会被自动调用。因此,我们可以在抽象类中使用构造函数。

注意:非抽象类不能有抽象方法,但抽象类可以有非抽象方法。 Reason与构造函数类似,不同之处在于我们可以调用super()而不是自动调用。此外,没有什么比抽象构造函数更像是没有任何意义了。

答案 4 :(得分:13)

它不仅可以,它始终如此。如果你没有指定一个,那么它有一个默认的没有arg构造函数,就像任何其他类一样。实际上,ALL类(包括嵌套类和匿名类)将获得默认构造函数(如果未指定一个类)(在匿名类的情况下,不可能指定一个,因此您将始终获得默认构造函数)。

具有构造函数的抽象类的一个很好的例子是Calendar类。通过调用Calendar.getInstance()获得Calendar对象,但它也有受保护的构造函数。它的构造函数受到保护的原因是只有它的子类可以调用它们(或者同一个包中的类,但因为它是抽象的,所以不适用)。 GregorianCalendar是扩展日历的类的示例。

答案 5 :(得分:6)

是的,抽象类构造函数通常用于超级调用所有子类共有的初始化事件

答案 6 :(得分:6)

抽象类可以有一个构造函数但是你不能创建一个抽象类的对象,那么你如何使用该构造函数?

当你在子类中继承那个抽象类时,你可以通过你的子类中的super(value)方法将值传递给它的(抽象的)构造函数,而不是你不继承构造函数。

所以使用super你可以在抽象类的构造函数中传递值,据我所知它必须是你的方法或构造函数中的第一个语句。

答案 7 :(得分:4)

虽然有很多好的答案,但我想给我2美分。

构造函数不构建对象。它用于初始化对象。

是的,Abstract类总是有一个构造函数。如果您没有定义自己的构造函数,编译器将为Abstract类提供默认构造函数。 以上适用于所有类 - 嵌套,抽象,匿名等。

抽象类(与接口不同)可以包含需要初始化的非最终非静态字段。您可以在抽象类中编写自己的构造函数来执行此操作。但是,在这种情况下,将不会有任何默认构造函数。

public abstract class Abs{
    int i;
    int j;
    public Abs(int i,int j){
        this.i = i;
        this.j = j;
        System.out.println(i+" "+j);
    }
}

在扩展上面的抽象类时要小心,你必须从每个构造函数显式调用super。任何构造函数的第一行都调用super()。如果你没有显式调用super(),Java会为你做这件事。 下面的代码不会编译:

public class Imp extends Abs{

public Imp(int i, int j,int k, int l){
    System.out.println("2 arg");
}
}

你必须像下面的例子一样使用它:

public class Imp extends Abs{

public Imp(int i, int j,int k, int l){
    super(i,j);
    System.out.println("2 arg");
}
}

答案 8 :(得分:3)

当然,抽象类可以有一个构造函数。通常,类构造函数用于初始化字段。因此,抽象类构造函数用于初始化抽象类的字段。如果要在子类的实例化之前初始化抽象类的某些字段,则可以为抽象类提供构造函数。抽象类构造函数也可用于执行与每个子类相关的代码。这可以防止代码重复。

我们不能创建抽象类的实例,但是我们可以创建从抽象类派生的类的实例。因此,当创建派生类的实例时,将自动调用父抽象类构造函数。

参考:This Article

答案 9 :(得分:2)

在具体的类中,声明具体类型Fnord的构造函数有效地暴露了两件事:

  • 代码可以请求创建Fnord实例的方法

  • 正在构建的Fnord 派生类型的实例可以请求初始化所有基类功能的方法。

虽然应该有一种方法可以分别控制这两种能力,但对于每种具体类型,一种定义都可以实现这两种能力。虽然第一种能力对于抽象类没有意义,但第二种能力对于抽象类来说和其他任何能力一样有意义,因此它的声明同样必要且有用。

答案 10 :(得分:2)

是的,是的。当创建继承类的实例时,将调用抽象类的构造函数。例如,以下是有效的Java程序。

// An abstract class with constructor
abstract class Base {
Base() { System.out.println("Base Constructor Called"); }
abstract void fun();
    }
class Derived extends Base {
Derived() { System.out.println("Derived Constructor Called"); }
void fun() { System.out.println("Derived fun() called"); }
    }

class Main {
public static void main(String args[]) { 
   Derived d = new Derived();
    }

}

这是上述代码的输出,

调用基础构造函数 派生的构造函数被称为

的引用: enter link description here

答案 11 :(得分:2)

考虑一下:

abstract class Product { 
    int value;
    public Product( int val ) {
        value= val;
    }
    abstract public int multiply();
}

class TimesTwo extends Product {
    public int mutiply() {
       return value * 2;
    }
}

超类是抽象的,并且有一个构造函数。

答案 12 :(得分:1)

是的,抽象类可以有构造函数!

以下是在抽象类中使用构造函数的示例:

abstract class Figure { 

    double dim1;        
    double dim2; 

    Figure(double a, double b) {         
        dim1 = a;         
        dim2 = b;         
    }

    // area is now an abstract method 

   abstract double area(); 

}


class Rectangle extends Figure { 
    Rectangle(double a, double b) { 
        super(a, b); 
    } 
    // override area for rectangle 
    double area() { 
        System.out.println("Inside Area for Rectangle."); 
        return dim1 * dim2; 
    } 
}

class Triangle extends Figure { 
    Triangle(double a, double b) { 
        super(a, b); 
    } 
    // override area for right triangle 
    double area() { 
        System.out.println("Inside Area for Triangle."); 
        return dim1 * dim2 / 2; 
    } 
}

class AbstractAreas { 
    public static void main(String args[]) { 
        // Figure f = new Figure(10, 10); // illegal now 
        Rectangle r = new Rectangle(9, 5); 
        Triangle t = new Triangle(10, 8); 
        Figure figref; // this is OK, no object is created 
        figref = r; 
        System.out.println("Area is " + figref.area()); 
        figref = t; 
        System.out.println("Area is " + figref.area()); 
    } 
}

所以我认为你得到了答案。

答案 13 :(得分:1)

由于抽象类可以包含所有访问修饰符的变量,因此必须将它们初始化为默认值,因此构造函数是必需的。 在实例化子类时,将调用抽象类的构造函数并初始化变量。

相反,接口确实只包含常量变量意味着它们已经初始化。所以界面不需要构造函数。

答案 14 :(得分:1)

是的,抽象类可以有一个构造函数。您可以在Abstract类中重载所需数量的构造函数。这些承包商可用于初始化扩展抽象类的对象的初始状态。我们知道我们不能创建一个抽象类的对象,因为对象是由“new”关键字创建的,而不是由构造函数创建的...它们仅用于初始化子类Objects的状态。

答案 15 :(得分:1)

为了实现构造函数链接,抽象类将具有构造函数。 编译器将Super()语句保留在子类构造函数中,该构造函数将调用超类构造函数。如果没有抽象类的构造函数,则违反了java规则,我们无法实现构造函数链接。

答案 16 :(得分:1)

Abstract类虽然无法实例化,但可以有一个构造函数。但是,抽象类中定义的构造函数可用于实例化此抽象类的具体类。检查JLS

  

如果尝试使用类实例创建创建抽象类的实例,那么这是一个编译时错误   表达

     

抽象类的子类本身不是抽象的   实例化,导致执行构造函数   抽象类,因此,字段初始化程序的执行   例如该类的变量。

答案 17 :(得分:1)

如javafuns here所述,这是一个例子:

public abstract class TestEngine
{
   private String engineId;
   private String engineName;

   public TestEngine(String engineId , String engineName)
   {
     this.engineId = engineId;
     this.engineName = engineName;
   }
   //public gettors and settors
   public abstract void scheduleTest();
}


public class JavaTestEngine extends TestEngine
{

   private String typeName;

   public JavaTestEngine(String engineId , String engineName , String typeName)
   {
      super(engineId , engineName);
      this.typeName = typeName;
   }

   public void scheduleTest()
   {
     //do Stuff
   }
}

答案 18 :(得分:0)

是的,您肯定可以添加一个,如前面提到的Abstract类变量的初始化。 但是,如果你没有明确声明一个,它无论如何都有一个隐含的构造函数“构造函数链接”工作。

答案 19 :(得分:0)

类中构造函数的用途是用于初始化字段,但不用于构建对象"。当您尝试创建抽象SuperClass的新实例时,编译器将给您一个错误。但是,我们可以继承一个抽象类Employee,并通过设置其变量来使用它的构造函数参见下面的示例

public abstract class Employee {
  private String EmpName;
  abstract double calcSalary();

  Employee(String name) {
    this.EmpName = name;// constructor of abstract class super class
  }
}

class Manager extends Employee{
 Manager(String name) {
    super(name);// setting the name in the constructor of sub class
 }
double calcSalary() {
    return 0;
 }
}

答案 20 :(得分:0)

包Test1;

公共类AbstractClassConstructor {

test_df %>% # Duplicates
  group_by(Type, Group) %>%
  filter(any_string_duplicates(Text))
#> # A tibble: 10 x 4
#> # Groups:   Type, Group [5]
#>       ID Type  Group Text                      
#>    <dbl> <chr> <dbl> <chr>                     
#>  1   100 A         1 Lorem ipsum dolor sit amet
#>  2   103 A         1 Lorem ipsum dolor sit amet
#>  3   107 B         1 Lorem ipsum dolor sit amet
#>  4   209 B         1 Lorem ipsum dolor sing eli
#>  5   300 C         1 Lorem ipsum dolor sit amet
#>  6   501 C         1 Lorem ipsum dolor sit amet
#>  7   799 B         2 Lorem ipsum dolor sit amet
#>  8   811 B         2 Lorem ipsum dolor sit amet
#>  9   812 C         3 Lorem ipsum dolor sit amet
#> 10   820 C         3 Lorem ipsum dolor sing eli

test_df %>% # Uniques
  group_by(Type, Group) %>%
  filter(!any_string_duplicates(Text))
#> # A tibble: 5 x 4
#> # Groups:   Type, Group [3]
#>      ID Type  Group Text                      
#>   <dbl> <chr> <dbl> <chr>                     
#> 1   105 A         1 consectetur adipiscing eli
#> 2   106 A         1 et dolore magna aliqua. Ut
#> 3   503 A         2 Lorem ipsum dolor sit amet
#> 4   711 A         2 consectetur adipiscing eli
#> 5   831 C         3 sed do eiusmod temporo eli

}

public AbstractClassConstructor() {

}

    public static void main(String args[]) {
       Demo obj = new Test("Test of code has started");
       obj.test1();
    }

答案 21 :(得分:-5)

是的......就像其他任何一个班级一样。它可以有一个构造函数,并在为基类创建对象后调用它。