DEV Community

TANIAOKA, Akihiro
TANIAOKA, Akihiro

Posted on

7章18

このJavaコードは、Sampleというクラスを定義し、その中にint型のプライベート変数numを持っています。Sampleクラスには、その変数numをセットするためのコンストラクタ、値を取得するためのgetNum()メソッド、そして値を設定するためのsetNum(int num)メソッドがあります。MainクラスのmainメソッドはSampleオブジェクトを作成し、そのgetNum()メソッドを呼び出しています。しかし、Sampleクラスのコンストラクタは空であり、渡された引数でnumを初期化していません。したがって、問題の答えを正しくするには、コンストラクタの中身を完成させる必要があります。

以下は、それぞれの選択肢についてのコメントです:

  • A. this.num = num;: これが正しい文です。thisキーワードは、現在のオブジェクトのnum変数を指し、渡された引数numをそれに代入します。
  • B. this->num = num;: これはJavaではなく、C++の文法です。
  • C. num = num;: これでは、引数のnumをそのまま自分自身に代入しようとしますが、この場合、インスタンス変数ではなく、ローカル変数のnumを指します。これは何も変更しません。
  • D. setNum(num);: これは機能しますが、通常はコンストラクタ内で直接フィールドを設定します。ただし、これを使っても正しくnumを設定することができます。
  • E. super.setNum(num);: この文は、現在のクラスが親クラスから継承しているメソッドsetNumを呼び出そうとしていますが、このコードには親クラスのメソッドを呼び出す必要はなく、またSampleクラスには親クラスが示されていません。

以下の2つのステートメントがコンストラクタで期待される動作を行うことになります:

  • A. this.num = num;: これはコンストラクタ内でインスタンス変数に引数の値を代入する正しい方法です。
  • D. setNum(num);: これはコンストラクタ内で既に定義されているセッターメソッドを使ってインスタンス変数numを設定します。

したがって、適切な選択肢はAとDです。どちらの方法もインスタンス変数numに値を代入するために使うことができますが、慣習的にはフィールドへの直接代入を行うAが一般的に使用されます。しかし、セッターメソッドを使用するDもまた有効であり、特にセッターに追加のロジックがある場合にはこの方法が適しています。この場合、セッターメソッドはただ単に代入するだけですが、将来的に検証などの追加のコードをセッターに入れるかもしれないと考えると、Dも適切な選択です。

追記

了解しました。以下のコードにコメントアウトを追加して、各部分の説明を行います。

class Sample {
    private int num; // クラスのプライベート変数numを宣言。

    public Sample(int num) {
        this.num = num; // コンストラクタ。引数で受け取ったnumをインスタンス変数numに代入。
        // または
        // setNum(num); // セッターメソッドを使用してnumを設定する別の方法。
    }

    public int getNum() {
        return num; // numの値を返すゲッターメソッド。
    }

    public void setNum(int num) {
        this.num = num; // セッターメソッド。引数で受け取ったnumをインスタンス変数numに代入。
    }
}

public class Main {
    public static void main(String[] args) {
        Sample s = new Sample(10); // Sampleオブジェクトを生成し、コンストラクタに10を渡す。
        System.out.println(s.getNum()); // sオブジェクトのgetNumメソッドを呼び出し、その結果を出力。
    }
}
Enter fullscreen mode Exit fullscreen mode

このコードは、Sampleクラスのインスタンスを生成してnum10を設定し、その値を取得してコンソールに出力する単純なプログラムです。設問に対する答えとしては、コンストラクタ内でthis.num = num; または setNum(num); のどちらか(または両方)を使うことが適切です。これにより、Sampleオブジェクトが生成された際にnumが適切に初期化されます。

補足

  • D. setNum(num);: は機能しますが、通常、Javaではコンストラクタ内で直接フィールドを設定することが推奨されています。直接フィールドに値を代入することにより、オブジェクトの新しいインスタンスが適切に初期化されることを保証するためです。セッターメソッドを使用することも技術的には可能ですが、この方法は一般的には避けられます。その理由は以下のとおりです:

追加のオーバーヘッド: セッターメソッドを呼び出すことは、直接フィールドにアクセスするよりもわずかにオーバーヘッドが大きくなる可能性があります。

不要なロジックの実行: セッターメソッドには通常、値の検証や変換などの追加的なロジックが含まれることが多いです。コンストラクタでこのようなロジックを実行する必要がない場合(例えば、オブジェクトの信頼できる初期化データが既にある場合など)は、不要な処理を避けるために直接フィールドに値を代入することが好ましいです。

インスタンスの不変性: オブジェクトが不変であるべき場合(つまり、一度作成された後はその状態が変わらない場合)、セッターメソッドを提供することは適切ではありません。コンストラクタでのみ状態を設定し、その後はオブジェクトの状態を変更できないようにすることが望ましいです。

ただし、コンストラクタ内でセッターを使用することが完全に間違っているわけではありません。例えば、以下のような場合にはセッターを使用することが有効です:

セッターメソッドに特別なロジックがあり、コンストラクタでもそのロジックを適用したい場合。
サブクラスでセッターメソッドをオーバーライドしており、サブクラスのロジックをコンストラクタからも活用したい場合。
最終的には、設計上の選択としてコンストラクタ内でセッターを使うか直接フィールドを設定するかは、そのクラスの要件や設計原則に依存します。明確なルールがあるわけではなく、状況に応じて最適な方法を選択する必要があります。

Top comments (0)