web-dev-qa-db-ja.com

抽象クラスはコンストラクタを持つことができますか?

抽象クラスはコンストラクタを持つことができますか?

もしそうなら、それはどのように使用できますか、そして何の目的のために?

554
Szere Dyeri

はい、抽象クラスはコンストラクタを持つことができます。このことを考慮:

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には、呼び出し元が値を指定できるようにするコンストラクターがあります。

抽象コンストラクタは、クラスの設定に必要な最小フィールドなど、クラスの制約や不変条件を強制するためによく使用されます。

注:親抽象クラスにはデフォルト(または引数なし)コンストラクターがないため、サブクラスで使用されるコンストラクターは明示的に親コンストラクターを呼び出す必要があります。

592

次のいずれかの状況にある場合は、抽象クラスでコンストラクタを定義します。

  • サブクラスのインスタンス化が実際に行われる前に、(抽象クラ​​スのフィールドに対して)何らかの初期化を実行したいのです。
  • abstractクラスでfinalフィールドを定義しましたが、宣言自体でfinalフィールドを初期化しませんでした。この場合、これらのフィールドを初期化するためのコンストラクタが必要です。

ご了承ください:

  • 複数のコンストラクタを(異なる引数で)定義できます。
  • 保護されているすべてのコンストラクタを定義できます(公開しても意味がありません)。
  • サブクラスのコンストラクタは抽象クラスのコンストラクタを1つ呼び出すことができます。にする必要があるかもしれません(抽象クラ​​スに引数のないコンストラクタがない場合)

いずれにせよ、コンストラクタを定義しなければ、コンパイラが自動的にコンストラクタを生成します(このコンストラクタはパブリックで、引数はなく、何もしません)。

147
jfpoilpret

はい、それはコンストラクタを持つことができ、それは他のクラスのコンストラクタと同じように定義され、振る舞います。抽象クラスを直接インスタンス化することはできず、拡張するだけなので、その使用は常にサブクラスのコンストラクターから行われます。

54
Lawrence Dol

はい 抽象クラスはコンストラクタを持つことができます

はい、クラスを抽象クラスとして定義した場合、インスタンス化することはできませんが、抽象クラスがコンストラクタを持つことができないという意味ではありません。各抽象クラスは、その抽象クラスの抽象メソッドを実装する具象サブクラスを持つ必要があります。

サブクラスのオブジェクトを作成すると、対応する継承ツリーのすべてのコンストラクタが上から下へのアプローチで呼び出されます。同じことが抽象クラスにも当てはまります。抽象クラスのオブジェクトは作成できませんが、抽象クラスの具象クラスおよびサブクラスのクラスのオブジェクトを作成すると、抽象クラスのコンストラクタが自動的に呼び出されます。したがって、抽象クラスにコンストラクタを含めることができます。

注意:非抽象クラスは抽象メソッドを持つことはできませんが、抽象クラスは非抽象メソッドを持つことができます。理由はコンストラクタのそれに似ていますが、違いは自動的に呼び出されるのではなくsuper()を呼び出すことができるということです。また、まったく意味がないため、抽象コンストラクタのようなものはありません。

33
Aniket Thakur

それができるだけでなく、それは常にします。指定しない場合は、他のクラスと同じように、デフォルトの引数なしのコンストラクタが使用されます。実際、ネストクラスや匿名クラスを含むすべてのクラスは、指定されていない場合はデフォルトコンストラクタを取得します(匿名クラスの場合は指定できないため、常にデフォルトコンストラクタを取得します)。

コンストラクタを持つ抽象クラスの良い例は Calendar クラスです。 Calendar.getInstance()を呼び出してCalendarオブジェクトを取得しますが、保護されているコンストラクタもあります。そのコンストラクタが保護されているのは、そのサブクラスだけがそれらを呼び出せるようにするためです(または同じパッケージ内のクラスですが、抽象的なのでこれは適用されません)。 GregorianCalendar は、Calendarを拡張するクラスの例です。

13
MattC

はい、できます。抽象クラスのコンストラクタは通常、すべてのサブクラスに共通の初期化イベントのスーパーコールに使用されます。

6
Jacob

抽象クラスはコンストラクタを持つことができますが、抽象クラスのオブジェクトを作成することはできません。そのコンストラクタをどのように使用しますか。

サブクラスでその抽象クラスを継承すると、サブクラスのsuper(value)メソッドを介してその(抽象の)コンストラクタに値を渡すことができますが、コンストラクタを継承する必要はありません。

そのため、superを使用すると、抽象クラスのコンストラクターに値を渡すことができます。私が覚えている限りでは、それはメソッドまたはコンストラクターの最初のステートメントでなければなりません。

6
Alok

良い答えはたくさんありますが、私は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");
}
}
4
Harshil

もちろん、抽象クラスはコンストラクタを持つことができます。一般にクラスコンストラクタはフィールドを初期化するために使用されます。抽象クラスコンストラクタは抽象クラスのフィールドを初期化するために使用されます。子クラスのインスタンス化が行われる前に抽象クラスの特定のフィールドを初期化する場合は、抽象クラスのコンストラクタを指定します。抽象クラスコンストラクタは、すべての子クラスに関連するコードを実行するためにも使用できます。これによりコードの重複が防止されます。

抽象クラスのインスタンスは作成できませんが、抽象クラスから派生したクラスのインスタンスは作成できます。したがって、派生クラスのインスタンスが作成されると、親の抽象クラスコンストラクタが自動的に呼び出されます。

参照: この記事

3
Raj Baral

このことを考慮:

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

スーパークラスは抽象クラスで、コンストラクタを持ちます。

2
S.Lott

具象クラスでは、具象タイプFnordのコンストラクターを宣言すると、事実上2つのことが明らかになります。

  • コードがFnordのインスタンスの作成を要求できる手段

  • 構築中のインスタンスFnordから派生した型のものが、すべての基本クラスの機能を初期化するように要求できる手段.

おそらくこれら二つの能力を別々に制御することができる手段があるべきですが、あらゆる具体的なタイプのために1つの定義が両方を可能にするでしょう。最初の能力は抽象クラスには意味がありませんが、2番目の能力は抽象クラスにも意味があります。したがって、その宣言は必要かつ有用です。

2
supercat

はい、そうです。そして、継承クラスのインスタンスが作成されたときに抽象クラスのコンストラクタが呼び出されます。たとえば、以下は有効な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();
    }

}

これは上記のコードの出力です。

呼び出された基本コンストラクター呼び出された派生コンストラクター

参照先: ここにリンクの説明を入力してください

2
chamzz.dot

コンストラクタチェーンを実現するために、抽象クラスはコンストラクタを持ちます。コンパイラは、スーパークラスコンストラクタを呼び出すサブクラスコンストラクタ内にSuper()ステートメントを保持します。抽象クラスのコンストラクタがないと、Javaの規則に違反し、コンストラクタチェーンを実現できません。

1
Anilkumar K S

はい、抽象クラスはコンストラクタを持つことができます!

これは抽象クラスでコンストラクタを使った例です:

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

だから私はあなたが答えを得たと思います。

1
Ketan G

はい、抽象クラスはコンストラクタを持つことができます。抽象クラスでは、必要なだけ多くのコンストラクタをオーバーロードできます。これらの契約者は、抽象クラスを拡張するオブジェクトの初期状態を初期化するために使用できます。オブジェクトはコンストラクタではなく「new」キーワードによって作成されるため、抽象クラスのオブジェクトを作成することはできません。サブクラスオブジェクトの状態を初期化するためだけに存在します。

1
Shubham Soni

インスタンス化することはできませんが、抽象クラスはコンストラクタを持つことができます。ただし、抽象クラスで定義されたコンストラクタは、この抽象クラスの具象クラスのインスタンス化に使用できます。 _ jls _ :を確認してください。

クラスインスタンス作成式 を使用して抽象クラスのインスタンスを作成しようとすると、コンパイル時エラーとなります。

それ自体抽象ではない抽象クラスのサブクラスはインスタンス化され、その結果抽象クラスのコンストラクタが実行され、したがってそのクラスのインスタンス変数のフィールド初期化子が実行されます。

1
i_am_zero

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

抽象クラス はすべてのアクセス修飾子の変数を持つことができるので、それらはデフォルト値に初期化されなければならないので、コンストラクタが必要です。子クラスをインスタンス化すると、抽象クラスのコンストラクタが呼び出され、変数が初期化されます。

それどころか、 interface は定数変数しか含まないので、それらはすでに初期化されています。だから、インターフェイスはコンストラクタを必要としません。

1
Arun Raaj

クラスの中のコンストラクタの目的は フィールドを初期化するのに使われます しかし "オブジェクトを構築する"ためには使われません。抽象スーパークラスの新しいインスタンスを作成しようとすると、コンパイラによってエラーが発生します。ただし、抽象クラス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;
 }
}
0
karto

はい、もちろん追加することができます。これは、抽象クラス変数の初期化についてすでに説明したとおりです。しかし、明示的に宣言しなければ、とにかく "Constructor Chaining"のための暗黙のコンストラクタが機能します。

0
Kedar Parikh