2011-01-25 11 views
32

abstractクラスのコンストラクタを直接呼び出すことでオブジェクトを作成することはできません。 abstractクラスのコンストラクタは、派生クラスからのみ呼び出すことができます。したがって、と思われます。抽象クラスのコンストラクタはprotectedまたはpackage-private(パッケージ内の派生クラスへのコンストラクタの使用を制限する例外的なケースは後者です)でなければなりません。しかし、Javaではabstractクラスのコンストラクタをpublicにすることができます。抽象クラスのpublicコンストラクタには十分な理由があります

は、それがむしろprotectedまたはパッケージプライベートよりも、publicするabstractクラスのコンストラクタを宣言する便利である任意の事情はありますか?

これは質問「Abstract class constructor access modifier」のかなり重複していない。はっきりあなたpublicするコンストラクタを宣言することができます。私はいつでもが良いかどうかを知りたいと思っています。理由があります。そこにはないと私には思われます。私はそれがC# has a similar peculiarityを参照してください。

+0

コンストラクタは、オブジェクトの「作成」とは関係ありません。これは、オブジェクトを「作成」しているときに呼び出される単なるメソッドです。したがって、抽象クラスは、(Subclassを介して)抽象クラスのインスタンスを作成する際に呼び出されるpublicコンストラクタを持つことができ、そのコンストラクタメソッドでは、メンバ変数を初期化するコードを記述します。 http://stackoverflow.com/questions/260666/can-an-abstract-class-have-a-constructor?lq=1 –

+1

コンストラクタはコンストラクタチェインで使用できる 'private'でもかまいません。 –

答えて

16

答えは、Javaのための同じである:

抽象クラスのpublicコンストラクタのための理由はありません。私は、コンパイラが不平を言っていない理由は、パブリックであるか保護されているかどうかは関係ありません。 (source

直接的なサブクラス以外のものから抽象クラスのコンストラクタを呼び出すことはできません。

抽象クラスのコンストラクタのアクセス修飾子に特別なルールを追加しても、その言語に便利なものは追加されません。


一つこの規則の例外のように見えるもの - 抽象クラスは、デフォルトコンストラクタを定義する場合は、サブクラスがコンストラクタを実装する必要はありません。これは合法である:

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

public class B extends A {} 

したがってnew B()を呼び出してBを作成できますが、はまだで、AではなくBを作成します。また、Aのコンストラクタがpublicであるか保護されているかどうかは関係ありません。あなたが持つことができ、それだけ

が実際に私たちは、単純なsuper()コールを行いBの「目に見えない」パブリックデフォルトコンストラクタを呼び出す...プライベートではありませんが、コンパイラが気づくと文句を言うでしょう...

-8

サブクラスのコンストラクタで定義していない場合はpublicコンストラクタです。 例

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で使用しています。

+3

これはJavaでは動作しません。また、戻り値の型( 'void')を指定するので、' Animal'クラスにコンストラクタを定義していません。 –

+2

'Animal'が(デフォルトではない)コンストラクタを持っているので(' public void Animal(String name) 'はコンストラクタではありません)、コンストラクタは' Cat'で*必須*です。 –

+0

これはうまくいく引数なしのコンストラクタを使用します。試してみると、コードはコンパイルされません。しかし、暗黙的なデフォルトコンストラクタは、スーパークラスコンストラクタが何であるかにかかわらず、常にクラス自身の可視性を持ちます。 – biziclop

-7

私には異端がありますが、...抽象クラスのコンストラクタに少なくとも1つの用途があります。

これは、コンストラクタのパラメータがどのように見えるかを指定するためです。

抽象コンストラクタを指定します(したがって、抽象クラスを抽象にします)。派生クラスは抽象ステータスを失うために、このコンストラクタを固有のシグネチャで実装する必要があります。

必須のコンストラクタシグネチャを指定する他の方法はありません(私に助けてください)。

+3

コンストラクタをprotectedにすると、コンストラクタパラメータの外観を指定できます。 – Raedwald

+0

trueですが、そうするためには、派生クラスがsuper()を呼び出すか、発生する可能性のあるinitステップが存在しないというリスクがあります。要約はこれが署名のみであり、実装ではないことを明確にしている。 - インタフェースがコンストラクタシグネチャを指定することが許可されている場合には最適です。しかし、彼らはしないので、私は抽象クラスを次善のものと考えています。 – foo

+3

あなたは 'super'を呼び出すことは避けられません。明示的に呼び出さない場合、暗黙的に呼び出されます。 – Raedwald

0

可視性は、javadocに表示される内容(特定の可視性レベルを除外するように選択されている場合)にも影響します。そうでない場合は、抽象クラスのpublicコンストラクタの使用になります。

コンストラクタを指定しない場合、クラスがpublicの場合、デフォルトのコンストラクタはpublicになります。最も簡単なオプションは、保護されたコンストラクタを強制するのではなく、そのことを可能にすることです。

逆の質問が明らかになるかもしれません:なぜ彼らは抽象クラスで保護されたコンストラクタを強制しませんでしたか?パブリックコンストラクタは何も変更しないので、時間がかかり複雑になります。

関連する問題