Java でコンストラクターをオーバーロードする
- Java のデフォルトコンストラクタ
- Java のパラメーター化されたコンストラクター
- コンストラクターのオーバーロードのないコード
- Java でのコンストラクターのオーバーロード
- コンストラクターのオーバーロードのベストプラクティス
- コンストラクターをオーバーロードする
このチュートリアルでは、Java でコンストラクターをオーバーロードする方法を紹介します。また、このトピックをよりよく理解するために従うことができるいくつかのサンプルコードをリストしました。
コンストラクターは、クラスオブジェクトにメモリを割り当て、そのオブジェクトのクラス属性を初期化するために呼び出されるメソッドです。クラスのコンストラクターが作成されていない場合、Java はデフォルトのコンストラクターを提供します。
たとえば、以下のクラスではコンストラクターが定義されていません。それでも、属性がデフォルト値(この場合は null)に初期化されている間に、そのクラスのオブジェクトを作成できます。
Java のデフォルトコンストラクタ
class Student {
String name;
Double gpa;
}
public class Main {
public static void main(String[] args) {
Student s = new Student();
System.out.println(s.name + "\t" + s.gpa);
}
}
出力:
null null
コンストラクターのオーバーロードの概念は、メソッドのオーバーロードに似ています。つまり、1つのクラスに複数のコンストラクターがあります。コンストラクターのオーバーロードは、さまざまな方法でクラスのメンバー変数を初期化するために行われます。
オーバーロードされたコンストラクターは必要な数だけ作成できます。唯一の条件は、オーバーロードされたコンストラクターは、それらが取るパラメーターの数とタイプが異なる必要があるということです。
たとえば、以下に示す Student
クラスで、student name
と GPA
の 2つの属性があるとします。クラスにはコンストラクターが定義されています。コンストラクターは、パラメーターとして文字列名と二重の GPA
を取り、新しいオブジェクトの対応する属性を初期化します。
Java のパラメーター化されたコンストラクター
class Student {
String name;
Double gpa;
Student(String s, Double g) {
name = s;
gpa = g;
}
}
public class Main {
public static void main(String[] args) {
Student s = new Student("Justin", 9.75);
System.out.println(s.name + "\t" + s.gpa);
}
}
出力:
Justin 9.75
コンストラクターのオーバーロードのないコード
新しいオブジェクトを作成するときに、学生名のみがコンストラクターに渡されるシナリオを考えてみます。この場合、GPA
は自動的に null
に設定されます。コンストラクターをオーバーロードせずに名前を渡すだけの場合、次のコンパイルエラーが発生します。
class Student {
String name;
Double gpa;
Student(String s, Double g) {
name = s;
gpa = g;
}
}
public class Main {
public static void main(String[] args) {
Student s = new Student("Justin");
System.out.println(s.name + "\t" + s.gpa);
}
}
出力:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The constructor Student(String) is undefined
at ConstructorOverloading.main(ConstructorOverloading.java:18)
Java でのコンストラクターのオーバーロード
上記の状況に対処するためのパラメーターとして、学生名のみを使用してオーバーロードされたコンストラクターを作成できます。このコンストラクターが呼び出されたときに、GPA
を null
に設定します。
class Student {
String name;
Double gpa;
Student(String s, Double g) {
name = s;
this.gpa = g;
}
Student(String s) {
name = s;
gpa = null; // Setting GPA to null
}
}
public class Main {
public static void main(String[] args) {
Student s1 = new Student("Justin");
Student s2 = new Student("Jessica", 9.23);
System.out.println(s1.name + "\t" + s1.gpa);
System.out.println(s2.name + "\t" + s2.gpa);
}
}
出力:
Justin null
Jessica 9.23
Student
オブジェクトが作成されたが、名前も GPA
も言及されていない別の状況を考えてみます。引数をとらず(デフォルトのコンストラクター)、name
および GPA
属性を null
に設定する別のオーバーロードされたコンストラクターを作成できます。
Java は、クラスに対して他のコンストラクターが作成されていない場合にのみ、デフォルトのコンストラクターを提供することに注意してください。ただし、このクラスの場合、コンストラクターは既に存在するため、デフォルトのコンストラクターを作成する必要があります。
class Student {
String name;
Double gpa;
Student(String s, Double g) {
name = s;
gpa = g;
}
Student(String s) {
name = s;
gpa = null;
}
Student() {
name = null;
gpa = null;
}
}
public class Main {
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student("Justin");
Student s3 = new Student("Jessica", 9.23);
System.out.println(s1.name + "\t" + s1.gpa);
System.out.println(s2.name + "\t" + s2.gpa);
System.out.println(s3.name + "\t" + s3.gpa);
}
}
出力:
null null
Justin null
Jessica 9.23
コンストラクターのオーバーロードのベストプラクティス
コンストラクターをオーバーロードするときに従うべき決まったガイドラインはありません。ただし、混乱を避け、エラーの範囲を減らすために従うことができる推奨されるベストプラクティスがいくつかあります。
- クラスのメンバー変数を参照するには、
this
キーワードを使用する必要があります。混乱を避け、コードを読みやすくします。 - より直感的なパラメーター名をコンストラクターに渡すこともできます。たとえば、コンストラクターが名前フィールドを初期化する場合、コンストラクターの署名は
Student(String s)
ではなくStudent(String name)
になります。this
キーワードを使用すると、name
と呼ばれるパラメーターと、name
とも呼ばれるクラス属性を区別できます。
Student
クラスの例を続けて、コンストラクター内で this
キーワードを使用しましょう。
class Student {
String name;
Double gpa;
Student(String name, Double gpa) // passing more intuitive parameter names
{
this.name = name; // using this keyword to avoid confusion
this.gpa = gpa;
}
Student(String name) {
this.name = name;
this.gpa = null;
Student()
this.name = null;
this.gpa = null;
}
}
- クラスが
単一のプライマリコンストラクタ
のみを持つこともお勧めします。残りのすべてのコンストラクタは、このプライマリコンストラクタを呼び出して属性を初期化する必要があります。 this()
関数を使用して、別のコンストラクターからコンストラクターを呼び出すことができます。this()
に渡す属性の数とタイプによって、呼び出されるコンストラクターが決まります。- コードの冗長性が減り、単一のコンストラクターのロジックを記述するだけで済みます。
Student
クラスでは、3つのオーバーロードされたコンストラクターが必要です。主要なコンストラクターは、パラメーターとしてname
とGPA
の両方をとるパラメーター化されたコンストラクターになります。他の 2つのオーバーロードされたコンストラクターは、単にプライマリコンストラクターを呼び出し、パラメーターの値をnull
として渡します。
class Student {
String name;
Double gpa;
Student(String name, Double gpa) // Primary Constructor that sets the attribute values
{
this.name = name;
this.gpa = gpa;
}
Student(String name) {
this(name, null); // Calling the primary constructor with GPA as null
}
Student() {
this(null, null); // Calling the primary constructor with both parameters as null
}
}
コンストラクターをオーバーロードする
コンストラクターのオーバーロードは、さまざまな方法でクラスの属性を初期化するために行われます。オーバーロードされたコンストラクターは、パラメーターの数、またはそれらに渡されるパラメーターのデータ型が異なる必要があります。
各コンストラクターの署名は、他のコンストラクターとは異なる必要があります。this
キーワードを使用して、クラス属性やその他のコンストラクターを参照する必要があります。これにより、コードの冗長性が減り、理解しやすくなります。