DEV Community

TANIAOKA, Akihiro
TANIAOKA, Akihiro

Posted on • Edited on

7章19

このJavaのコードは、継承に関する問題です。Parentクラスがあり、それを継承するChildクラスが定義されています。両クラスにはnameというフィールドがあり、Parentクラスにはnameフィールドを返すgetName()メソッドがあります。

MainクラスではChildクラスのインスタンスを作成し、nameフィールドに"sample"を設定してから、そのnameを取得して表示しようとしています。

ここでの重要なポイントは、ChildクラスがParentクラスのnameフィールドを隠蔽していることです。Childのインスタンスでnameにアクセスすると、Childクラスのnameが使われますが、getName()メソッドはParentクラスに定義されており、this.nameとしてParentクラスのnameフィールドを参照します。しかし、Childクラスのコンストラクタを通じてnameが初期化されないため、Parentクラスのnameフィールドはnullのままです。

結果として、System.out.println(child.getName());Parentクラスのnameフィールドの値を表示しようとしますが、それはnullのままなので、出力は[null]となります。

したがって、選択肢の中で正しい答えは B. [null] と表示される です。

以下はコメントを加えたコードです。

// Parentクラス定義
class Parent {
    String name; // Parentクラスのnameフィールド

    String getName() { // Parentクラスのnameフィールドを返すメソッド
        return this.name; // thisはParentクラスのインスタンスを指す
    }
}

// ChildクラスはParentクラスを継承
public class Child extends Parent {
    String name; // Childクラスもnameフィールドを持っている(Parentクラスのnameフィールドを隠蔽)
}

// メインクラス
public class Main {
    public static void main(String[] args) {
        Child child = new Child(); // Childクラスのインスタンスを作成
        child.name = "sample"; // Childクラスのnameフィールドに"sample"を設定
        // getName()メソッドを呼び出すと、Parentクラスのnameフィールドの値(null)が返される
        System.out.println(child.getName());
    }
}
Enter fullscreen mode Exit fullscreen mode

追記

"sample"を出力させるためには、以下のいずれかの方法でParentクラスのname変数を設定する必要がある

  1. コンストラクタを通じてnameを設定する。
  2. setNameメソッドをParentクラスに追加して、そのメソッドを使ってnameを設定する。
  3. Childクラスでname変数を宣言せず、代わりに継承されたname変数に直接値を設定する。

具体的には、以下のような変更を行います:

class Parent {
    String name;
    String getName() {
        return this.name;
    }
    void setName(String name) {
        this.name = name;
    }
}

public class Child extends Parent {
    // 'String name;' を削除
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        // child.name = "sample"; を変更
        child.setName("sample");
        System.out.println(child.getName());
    }
}
Enter fullscreen mode Exit fullscreen mode

Childクラスのname宣言を削除し、Parentクラスのname変数に直接アクセスしています。また、setNameメソッドをParentクラスに追加し、このメソッドを使ってnameの値を設定しています。これで"sample"という文字列が出力されるようになります。

補足

設問で見られる問題は、ParentクラスとChildクラスの両方にnameというフィールドが存在している点です。Javaでは、サブクラスがスーパークラスと同じ名前のフィールドを持つとき、サブクラスのフィールドがスーパークラスのフィールドを「隠蔽」します。これをフィールドのシャドーイングと言います。

このコードにおいてChildクラスのオブジェクトを作成し、Childクラスのnameフィールドに"sample"という値を設定します。しかし、getName()メソッドはParentクラスに定義されており、このメソッドはParentクラスのnameフィールドの値を返します。Parentクラスのnameフィールドは初期化されていないため、nullが返されます。

つまり、child.name = "sample";というコード行はChildクラスのnameフィールドに"sample"を設定しますが、child.getName()ParentクラスのgetName()メソッドを呼び出し、これはParentクラスのnameフィールドの値を返すため、結果としてnullが表示されます。

Top comments (0)