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

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

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

756947 次浏览

考虑这个:

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;
}
}

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

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

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

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有一个构造函数,允许调用者指定值。

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

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

如果您处于以下情况之一,您将在抽象类中定义构造函数:

  • 你想表演一些 初始化(到字段 抽象类)在 子类的实例化实际上 发生
  • 您已经在 抽象类但你没有 在声明中初始化它们 在这种情况下,你必须有 一个构造函数来初始化这些 字段

注意:

  • 你可以定义不止一个 构造函数(具有不同 参数)
  • 你可以(应该?)定义你所有的 构造函数保护(使它们 不管怎样,公开是没有意义的)
  • 您的子类构造函数可以 调用抽象的一个构造函数 类;它甚至可以必须称之为 (如果没有no-arg构造函数 在抽象类中)

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

抽象类可以有构造函数

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

当我们创建任一子类的对象时,都会采用自上而下的方式调用对应继承树中的构造函数。抽象类也是如此。虽然我们不能创建抽象类的对象,但当我们创建一个具体的、抽象类的子类的类对象时,会自动调用抽象类的构造函数。因此我们可以在抽象类中拥有构造函数。

注意:非抽象类不能有抽象方法,但抽象类可以有一个非抽象方法。原因与构造函数相似,区别在于我们可以调用Super()而不是自动调用。此外,没有什么比抽象构造函数更好的了,因为它根本没有意义。

正如javafuns这里所描述的,这是一个例子:

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
}
}

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

它不仅可以,而且总是可以。如果你不指定一个,那么它就有一个默认的no arg构造函数,就像任何其他类一样。事实上,所有类,包括嵌套类和匿名类,如果没有指定,都将获得一个默认构造函数(在匿名类的情况下,不可能指定一个,所以你将始终获得默认构造函数)。

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

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

  • 一种方法,代码可以通过这种方法请求创建FNord的实例

  • 一种方法,通过这种方法,从Fnord派生的类型的实例可以请求初始化所有基类特征。

虽然也许应该有一种方法可以分别控制这两种能力,但对于每一个具体类型,一个定义将同时启用这两种能力。尽管第一种能力对抽象类没有意义,但第二种能力对抽象类的意义与对任何其他类的意义一样,因此它的声明同样必要和有用。

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

是的,您当然可以添加一个,正如已经提到的抽象类变量的初始化。 但是如果你没有显式声明一个,它无论如何都有一个隐式的构造函数来“构造函数链”工作。

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

这是一个在抽象类中使用构造函数的示例:

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());
}
}

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

抽象类可以有一个构造函数,尽管它不能实例化。但是抽象类中定义的构造函数可用于实例化该抽象类的具体类。检查JLS

如果尝试使用类实例创建创建抽象类的实例,则会出现编译时错误

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

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

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

问题是,当你继承子类中的抽象类时,你可以通过子类中的超(值)方法将值传递给它的(抽象的)构造函数,不,你不继承构造函数。

因此,您可以在抽象类的构造函数中传递值,并且据我所知,它必须是您的方法或构造函数中的第一条语句。

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

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

参考:这篇文章

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

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

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

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

抽象类(与接口不同)可以有需要初始化的非最终非静态字段。你可以在抽象类中编写自己的构造函数来做到这一点。但是,在这种情况下,不会有任何默认构造函数。

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);
}
}

在扩展抽象类时要小心,你必须从每个构造函数中显式调用超函数。任何构造函数的第一行调用超()。如果你没有显式调用超(),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");
}
}

是的。当创建继承类的实例时,会调用抽象类的构造函数。例如,以下是一个有效的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();
}


}

这是上面代码的输出,

调用基本构造函数 派生构造函数调用

引用: 在此处输入链接描述

类中构造函数的目的是用于初始化字段,而不是“构建对象”。当你尝试创建抽象SuperClass的新实例时,编译器会给你一个错误。然而,我们可以继承一个抽象类员工并通过设置其变量来使用它的构造函数

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;
}
}

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

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

package Test1;


public class AbstractClassConstructor {


public AbstractClassConstructor() {
        

}


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


abstract class Demo{
protected final String demoValue;
       

public Demo(String testName){
this.demoValue = testName;
}
       

public abstract boolean test1();
}


class Test extends Demo{
       

public Test(String name){
super(name);
}


@Override
public boolean test1() {
System.out.println( this.demoValue + " Demo test started");
return true;
}
   

}