![](https://i0.wp.com/media.dev.to/cdn-cgi/image/width=1000,height=500,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh8vslkqqlz4jlygnydc0.png?w=1200&ssl=1)
失礼しました、コードにはもう一箇所コンパイルエラーが発生します。以下に修正されたコメントアウトを追加したコードを示します。
// SubSampleクラス定義部、Sampleクラスを継承
public class SubSample extends Sample { // ... // SubSampleクラスのコンストラクタ(価格を引数に取る) // このコンストラクタは、親クラスSampleのnameとnumを初期化していないため、 // SubSampleオブジェクトが作成された際に、nameとnumがデフォルト値のnullと0で初期化される public SubSample(int price) {
//ここにsuper(); を呼び出す記述がないのでコンパイルエラーが発生 this.price = price; } // コンストラクタでコンパイルエラーが発生する箇所(文字列、数値、価格を引数に取る) public SubSample(String name, int num, int price) { super(name, num); // 親クラスのコンストラクタを呼び出し this(price); // コンパイルエラー:他のコンストラクタを呼び出す場合、それは最初の命令でなければならない。 // また、super()が既に呼び出されているため、this()を呼び出すことはできない。 } // ...
}
ここで指摘する二つの問題点は以下の通りです:
- Javaの継承において、すべてのコンストラクタは、直接または間接的に親クラスのコンストラクタを呼び出さなければなりません。もし親クラスにデフォルトコンストラクタ(引数なしのコンストラクタ)が存在しない場合、サブクラスのコンストラクタは明示的に親クラスの存在するコンストラクタを呼び出す必要があります。
具体的には、SubSample(int price) コンストラクタで super(); を呼び出す記述がないと、コンパイルエラーが発生します。これは、Sample クラスにデフォルトコンストラクタが存在しないためです。Sample クラスには引数を取るコンストラクタのみが定義されている場合、SubSample コンストラクタはこれを明示的に呼び出す必要があります。
したがって、SubSample(int price) のコンストラクタでは、適切な super(…); の呼び出しが必要です。例えば、親クラスのフィールド name と num にデフォルト値を設定することでこれを実現できます。
-
SubSample(String name, int num, int price)
コンストラクタでは、super(name, num);
の後にthis(price);
を呼び出していますが、これはコンパイルエラーを引き起こします。this
またはsuper
呼び出しは、コンストラクタの最初の命令でなければならないためです。さらに、一つのコンストラクタでsuper
とthis
の両方を呼ぶことはできません。
追記
コンパイルエラーを回避するためには、SubSample
クラスのコンストラクタを修正する必要があります。次のように変更できます:
SubSample(int price)
コンストラクタでは、親クラスSample
のデフォルトコンストラクタを呼び出して適切に初期化するか、もしくは親クラスにデフォルトコンストラクタを追加する必要があります。ただし、現在のSample
クラスには引数なしのデフォルトコンストラクタが定義されていないため、SubSample
コンストラクタ内で親クラスのフィールドを明示的に初期化するか、親クラスにデフォルトコンストラクタを追加する必要があります。SubSample(String name, int num, int price)
コンストラクタでは、this(price);
の呼び出しを削除し、代わりにprice
フィールドを直接設定します。
これらの変更を加えたコードは次のようになります:
// Sampleクラスにデフォルトコンストラクタを追加
public class Sample { // ... // デフォルトコンストラクタを追加(オプション) public Sample() { // デフォルトの値でフィールドを初期化 this.name = null; this.num = 0; } // ...
} public class SubSample extends Sample { // ... // SubSampleクラスのコンストラクタ(価格を引数に取る) public SubSample(int price) { super(); // 親クラスSampleのデフォルトコンストラクタを呼び出し(もし追加した場合) this.price = price; } // SubSampleクラスのコンストラクタ(文字列、数値、価格を引数に取る) public SubSample(String name, int num, int price) { super(name, num); // 親クラスのコンストラクタを呼び出す this.price = price; // priceフィールドを直接設定する } // ...
}
これにより、SubSample
の各コンストラクタは適切に Sample
クラスのコンストラクタを呼び出し、price
フィールドも適切に設定するため、コンパイルエラーは発生しなくなります。
Discover more from Coursity
Subscribe to get the latest posts sent to your email.