web-dev-qa-db-ja.com

いつコンストラクタを呼び出し、いつJavaでメソッドを呼び出すのですか?

Javaでのコンストラクターの使用法を完全に理解するのに苦労しています。

これまでにコンストラクタについて学んだことは次のとおりです。

  • クラスと同じ名前
  • 略語俳優
  • 過負荷
  • 戻り型なし
  • クラスのオブジェクトを作成する
  • すべてのクラスにはデフォルトのコンストラクターがあります

たとえば、呼び出す必要のあるクラスから文字列を返す必要がある場合、メソッドを作成できます。つまり、コンストラクターは何も返さないので十分ではありません。

質問への回答を試みます

意味を説明するために、2つのコンストラクターと、文字列を返す2つのメソッドを持つクラスを作成しました。

public class HelloWorldConstructor {
    public HelloWorldConstructor() { }

    public HelloWorldConstructor(String a) {
        saySomething(a);
    }

    public HelloWorldConstructor(String a, String b) {
        saySomething(a, b);
    }

    void saySomething(String a) {
        System.out.println(a);
    }

    void saySomething(String a, String b) {
        System.out.println(a + ", " + b);
    }
}

オプション1

クラスにあるメソッドを呼び出すことで文字列を返すことが可能です。

public class CallConstructor {
    public static void main(String[] args) {
        HelloWorldConstructor hwc = new HelloWorldConstructor();

        hwc.saySomething("allo");
        hwc.saySomething("allo", "allo");
    }
}

戻り値:

allo
allo, allo

オプション2

コンストラクタを直接呼び出すことによって文字列を返すことも可能です。

public class CallConstructor2 {
    public static void main(String[] args) {
        new HelloWorldConstructor("allo");
        new HelloWorldConstructor("allo", "allo");
    }
}

オプション1と同じ結果を返します。

ディスカッション

オプション2を選択した場合、オプション1で示した1つではなく2つのオブジェクトを作成する必要がありますが、いつオプション2を選択し、いつオプション1を選択しますか?この場合、1つのオブジェクトが作成されるため、オプション1を選択する方が良いと思いますが、オプション2は、他の状況が当てはまる場合に適しています。

Javaでのコンストラクターの使用

この例のコンストラクターは、クラスメンバーに初期値を与えるだけです。

https://stackoverflow.com/a/19941847/2777965

コンストラクターは、クラスのインスタンスを初期化するために使用されます。コンストラクターを使用して、オブジェクトに関する初期状態またはその他の重要な情報を指定するパラメーターを持つ新しいオブジェクトを頻繁に作成します

コンストラクターに関する理論とQ&Aについて読んだ後、それらを完全に理解するのに苦労しています。コンストラクタの呼び出し方法とメソッドの呼び出し方法は知っていますが、これを合理化することはできません。

  • ...の場合、コンストラクターを直接呼び出す必要があります。
  • コンストラクタのオーバーロードは次の場合に行われます...
  • メソッドは、デフォルトのコンストラクターを呼び出すことによって直接呼び出されます...
2
030

新しいオブジェクトインスタンスを作成する場合は、コンストラクターを呼び出します。たとえば、クラスButtonがあり、新しいButtonインスタンスを作成する場合は、コンストラクターを呼び出します。

新しいオブジェクトが必要ない場合は、コンストラクタを使用しないでください。あなたの例では、コンストラクタをメソッドを呼び出す複雑な方法として使用していますが、実際には、作成されたオブジェクト(new式の結果)を何にも使用していません。これは、コンストラクターを呼び出す必要がないという明確なヒントです。 saySomethingを静的にした場合、コンストラクターを呼び出す必要はありません。

混乱の理由は、おそらくHelloWorldConstructorクラスが実際には出力を書く以外の目的を持っていないためです。したがって、インスタンスを1つ持つべきか2つ持つべきかは明らかではありません。実際には、インスタンスはまったく必要ありません。

6
JacquesB

クラスと同じ名前

確かに、Java

略語俳優

本当

過負荷

本当

戻り型なし

まあ...明示的なリターンはありません。 ctorには常に暗黙的な戻り値の型があります。クラスはタイプです。 ctorは、newキーワードと一緒に使用すると、作成したオブジェクトを返し、そのオブジェクトのタイプはクラスです。ありがたいことに、Actorを定義するときに、クラス名をもう一度言う必要はありません。

クラスのオブジェクトを作成する

それはそれがすることです。

すべてのクラスにはデフォルトのコンストラクターがあります

うーん、ダメ。ウィキペディアがそれを置くように:

JavaとC#の両方で、「デフォルトコンストラクタ」は、クラスにコンストラクタが定義されていない場合にコンパイラによって自動的に生成されるnullaryコンストラクタを指します。デフォルトコンストラクタは、スーパークラスのnullaryを暗黙的に呼び出します次に、コンストラクターは空の本体を実行します。

Wikipedia:デフォルトのコンストラクタ

したがって、すべてのクラスにデフォルトのコンストラクターがあるわけではありません。すべてのクラスにはコンストラクタがあります。明示的にコンストラクタを定義しない場合、デフォルトのコンストラクタのみが含まれます。

ところで、「nullaryコンストラクター」は、引数なしのコンストラクターを表現するための素晴らしい方法です。

たとえば、呼び出す必要のあるクラスから文字列を返す必要がある場合、メソッドを作成できます。つまり、コンストラクターは何も返さないので十分ではありません。

うーん。見てください 文字列を「返す」コンストラクタ があります。それらはすべて String class にあります。

意味を説明するために、2つのコンストラクターと、文字列を返す2つのメソッドを持つクラスを作成しました。

いいえ、していません。出力は戻りません。コンストラクタは文字列を返しません。 HelloWorldConstructorタイプのオブジェクトを「返す」。

これがコンパイルされる理由です:

HelloWorldConstructor hwc = new HelloWorldConstructor();

オプション1:クラスにあるメソッドを呼び出すことで文字列を返すことが可能です。

メソッドが文字列を返した場合です。彼らは無効を返します。繰り返しますが、出力は戻りません。

オプション2:コンストラクタを直接呼び出して文字列を返すこともできます。

文字列を出力することを意味します。はい、あなたはコンストラクタに、神が意図したように、単にオブジェクトを構築する以外に他のことをさせることができます。 それが良い考えだという意味ではありません

オプション2を選択した場合、オプション1で示した1つではなく2つのオブジェクトを作成する必要がありますが、いつオプション2を選択し、いつオプション1を選択しますか?この場合、1つのオブジェクトが作成されるため、オプション1を選択する方が良いと思いますが、オプション2は、他の状況が当てはまる場合に適しています。

オブジェクトの構築とオブジェクトの使用は、別の場所で行う必要があります。このようにマッシュアップすると、混乱するだけです。

...の場合、コンストラクターを直接呼び出す必要があります。

オブジェクトを構築しているとき。それを便利な変数に入れて、それを使用するものに渡します。

コンストラクタのオーバーロードは次の場合に行われます...

...オブジェクトが何に依存するかを決めることはできません。同じオブジェクトを作成する多くの方法を考えることができる場合、それらの多くの方法でそれを作成する多くのコンストラクターを作成します。

メソッドは、デフォルトのコンストラクターを呼び出すことによって直接呼び出されます...

申し訳ありませんが、これは意味がありません。オブジェクトを使用するときは、オブジェクトのメソッドを呼び出します。コンストラクターを構築するとき(デフォルトかどうか)にコンストラクターを呼び出します。

繰り返しますが、同時にビルドして使用する必要はありません。実際、そうしない方がいいです。ポリモーフィズムは、話している内容が正確にわからない場合にのみ機能します。

いつコンストラクタを呼び出し、いつJavaでメソッドを呼び出すか?

私がこれに対して持っている最良の答えは Dependency Injection から来ています。これは、コールスタックをできるだけ高く構築することを示しています。これは主に構築を行うことを意味します。個人的には、いくつかの Cretional Patterns を使用してもかまいませんが、メインから少し離れますが、動作コードはそこから遠ざけます。

4
candied_orange

プログラマーとしての私たちの仕事は、実際のさまざまなドメインに自動化を提供することです。そのためには、さまざまなドメインの概念、それらの関係、およびそれらの動作や機能を表す必要があります。

プログラミングでは、抽象化を定義するためのプログラミング言語の機能を使用して、さまざまな概念、関係、および動作を表現します。一方で、それらはいくつかのドメインの概念、関係、および動作をモデル化する一方で、一方で、それらは、消費するクライアントプログラマー(多くの場合、自分自身)から保護することを好む内部実装の詳細(状態やアルゴリズムなど)を持っているためです。複雑さを軽減し、プログラマーの負担を軽減します。

クラスは、抽象化を作成するための1つのメカニズムです。これにより、消費するクライアントプログラマが操作できる単一のエンティティにメソッドと状態をバンドルできます。

重要なのは、クラスコンストラクトがカスタマイズ可能なインスタンスを可能にすることです。インスタンスのカスタマイズは通常、コンストラクターに渡されるパラメーターを介して行われます。コンストラクターは、インスタンスを特定の値または特定の他のオブジェクトにバインドする機能を提供します。

インスタンスが構築されると、そのメソッドを使用して、概念の動作と関係にアクセスするためにインスタンスを使用できるようになります。

通常、抽象化を使用して、懸念を分離し、オブジェクトを1か所で作成し、それらを他の場所で使用します。オブジェクトの作成は、ある種のマイルストーンを表し、作成されたインスタンスは、他の使用しているクライアントプログラマが使用するために引き渡すことができます。作成方法に関係なく、同じタイプ(クラスまたはインターフェース)の異なるオブジェクトインスタンスを操作できます。


あなたのクラスHelloWorldConstructorは、明らかにあなたの質問のための単なる任意のサンプルです—私たちは通常、構築する能力に由来するのではなく、そのインスタンスが表す抽象化の後にクラスに名前を付けることはありません。

このクラスは、状態を持たないという点でも非常に単純化されています。 (状態のないインスタンスがあることは時々合理的ですが、その有用なシナリオは、通常、いくつかのインターフェース(または基本クラス)を共有する複数の異なるクラスを含みます。)状態がないと、コンストラクターは何もバインドしません—別の言い方をすれば、コンストラクターは、カスタマイズされたインスタンスの作成に参加していません。

とはいえ、オプション1は、インスタンスを作成して後で使用するため、オブジェクト指向プログラミングのスタイルになっています。これは、コードのすぐ隣の行で行われます。

オプション2は、コンストラクターですべての作業を行ってから、作成されたインスタンスを破棄するため、実質的には手続き型のプログラミング(つまりOOPではない)です。


典型的なシナリオは、コンストラクターを使用してインスタンスをカスタマイズし、作成したら、カスタマイズしたインスタンスを、そのクラスの任意のインスタンスで機能するより一般的なコードに渡します。そのより一般的なコードは、カスタマイズされたインスタンスでいくつかの有用な動作を実行します。

たとえば、名前を文字列として受け取るには、コンストラクターにパラメーターを追加します。現在、建設業者の仕事は、単にその名前を取得することです。

_public class SayHi {
    private String name;

    public SayHi(String toWhom) {
        name = toWhom;  // capture customization parameter
    }

    public void saySomething(String a) {
        System.out.println(name + ": " + a);
    }
}
_

これで、異なるようにカスタマイズされたインスタンスnew SayHi("Erik") ... new SayHi("030")を作成し、それらの異なるインスタンスを同じコードで使用できます。

3
Erik Eidt