• ベストアンサー

コンストラクタについて

コンストラクタにパラメータを指定するのは注意が必要という話を聞きました。 例) public Test(String str){ this.str_ = str; } なぜ注意すべきなのでしょうか? やはりパラメータを引数にとる時は以下のように書くのがよいのでしょうか? 例) public String test(String str){ ~ ~ プログラミングの先輩方、ぜひご教授ください。

  • Java
  • 回答数2
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
noname#247307
noname#247307
回答No.2

「注意が必要」だけだと、なんとも返事がしにくい感じがします。「よくない」ということなのか、ただ単に「ここに注意しないといけない」ということなのか。 私自身は、コンストラクタにパラメータを指定することを否定的に耳にした記憶はありません。ですので、別に「しないほうがいい」ということではないと思います。 「注意すべき」ということで、ちょっと思いついたのは以下の2点です。 ・引数付きコンストラクタを定義した際、デフォルトコンストラクタの定義を忘れて、後で予想外のところで叱られる、ということが往々にしてあります。 ・デフォルトコンストラクタと引数付きコンストラクタを用意した場合、コンストラクタの呼び出し順はどうなるのか、考える必要があります。どのメソッド内でthis()して、どこでsuper()するか、きちんと設計しないといけません。よく、複数のコンストラクタをもったクラスで、すべてのコンストラクタで片っ端からsuperしてるのを見たりしますので。 他にもあるのかも知れませんが、今思い出さないので……。いずれも「注意しましょう」ということであって、「だから引数付きコンストラクタはよくない」というわけではありませんので、念のため。

hanabi-68
質問者

お礼

なるほど。 しない方がいいというわけではないのですね! とてもわかりやすい説明です! ご回答ありがとうございます。

その他の回答 (1)

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.1

以下の例のように外部から値を書き換えられ、カプセル化が完全ではなくなるから、じぁないかと思います。 class Bust { private int value; public void setValue(int aValue) { value = aValue; } public int getValue() { return value; } } class Chihaya { private final Bust bust; public Chihaya(final Bust b) { bust = b; } public Bust getBust() { return bust; } } public class TestBad { public static void main(String[] args) { Bust b = new Bust(); b.setValue(91); Chihaya c = new Chihaya(b); System.out.println("value of Chihaya's Bust : " + c.getBust().getValue()); b.setValue(72); System.out.println("value of Chihaya's Bust : " + c.getBust().getValue()); } } というか、あなたが提示した下の例はコンストラクタではなくなっています。

hanabi-68
質問者

お礼

なるほど! コードまで書いてくださいましてありがとうございます! ご回答ありがとうございます!

関連するQ&A

  • コンストラクタでvar ?

    javascriptのコンストラクタについて。 下記のコードで、変数を2つ宣言しています(★)が、 下部のfor文で、その変数名を引数のstr,numにすれば、★での宣言は不要ですか? 宣言しとくと何かメリットがあるのでしょうか? var Repeater = function(str, num){ var string = str, //★ number = num;     //★ this.repeat = function (){ var i, result = ""; for(i = 0; i < number; i++ ) { result += string; } return result; }; }; new Repeater("abc", 3).repeat(); あるサイトから引用

  • コンストラクタの動作について

    下記のソースについて質問があります。 public class Test{ private String msg; public Test(){ this("Good morning"); } public Test(String msg){ msg = msg; } public String toString(){ /*(2)*/ return ("msg:" + msg); } public static void main(String args[]){ System.out.println(new Test()); /*(1)*/ } } このコードをコンパイルした出力結果は、 msg:null となるのですが、ここの仕組みがわかりません。 (1)でTestクラスのコンストラクタを呼び出し、msgに"Good morning"を設定し、 処理が終わると思うのですが、(2)の処理も行われてしまいます。 (1)では、Testのコンストラクタを設定しているだけに見えてしまうのですが、 (2)まで処理が行われるのは、何故かのかをご教授の程お願い致します。

    • ベストアンサー
    • Java
  • コンストラクタ について

    以下のように、String.h にクラスが定義されています。 class String { public:   String(); private:   char* str; }; それから String.cpp にて、以下のように関数があります。 #include "String.h" String::String() : str(NULL) {   str = new char[15]; } これを、main() から呼ぶにはどのようにしたらいいのでしょうか。 初心者の質問で具にもつかない質問かもしれませんが、一般的な例を教えてください。

  • VB2008: 継承の場合のコンストラクタの書き方?

    ' ================================================================== ' クラス TEST1 ' ================================================================== <Serializable()> Public Class TEST1   Private _Member1 As String   Private _Member2 As String   ' //   ' // パラメータを持つ初期化   ' //   Public Sub New(ByVal aMember1 As String, ByVal aMember2 As String)     _Member1 = aMember1     _Member2 = aMember2   End Sub End Class ' =========================== ' クラス TEST1 の派生クラス ' =========================== <Serializable()> Public Class NEWTEST1 Inherits TEST1 Private _Member1 As New TEST1 Private _Member2 As New TEST1 End Class これでもOKかと思うのですが・・・。 パラメータ化されていないコンストラクタをクラス TEST1 に書くように促すエラーがでます。 もちろん、パラメータを持たないコンストラクタを用意すればエラーは回避できます。 問題は、「Visual Basic のプログラミングガイド」からその理由を読み取れないことです。 >Visual Basic のオブジェクトの概要 >クラスについて >オブジェクトの作成と使用 まだ、ここしか読んでいません。 が、どうにも気になったので質問します。 1、エラーの回避策としては何が正しいのか? 2、その根拠は? この2つが知りたいです。

  • コンストラクタの記述について ―引数を持ったクラスを継承する場合―

    コンストラクタの記述について ―引数を持ったクラスを継承する場合― ActionScript3.0でプログラミングをしています。 クラスの継承に挑戦したのですが、うまくいきません。 コンストラクタの記述は、何か特別なものが必要なのでしょうか? ■コンストラクタに引数なし → 成功。 ■コンストラクタに引数あり → 失敗。  エラー「No default constructor found in base class <親クラスの名前>」。 ■エラーの出るソース↓ ・Main.as(コンストラクタ内抜粋)     var parent:Parent = new Parent(100);     var child:Child = new Child(200); ・Parent.as package {   import flash.display.Sprite;      public class Parent extends Sprite {     protected var str:String = "親クラスのプロパティ";     public function Parent(inNum:Number):void {       trace("親クラス, ", str, inNum);     }   } } ・Child.as package {   import Parent;   public class Child extends Parent {     public function Child(inNum:Number):void { //■エラー。       trace("子クラス, ", str, inNum);     }   } } ご存知の方、よろしくお願いします。 よろしくお願いします!

    • ベストアンサー
    • Flash
  • コンストラクタからメソッドを呼んではいけない?

    会社の先輩から、 「コンストラクタでメソッドを呼ぶな!」をいわれ 理由も聞かずにソースを修正したのですが、 なぜコンストラクタからメソッドを呼んではいけないのでしょうか? 例: public class MyClass{ public MyClass(){ test(); } private void test(){ System.out.println("test"); } } よろしくお願いします。

    • ベストアンサー
    • Java
  • 【.NET】コンストラクタをあとで呼出す方法

    .NET初心者です。 今VB.NETでVB6向けの自作COMクラスライブラリを作成しています。 自作クラスはStreamWriterクラスのラッパークラスとしてStreamWriterと継承関係にあります。 COMは引数なしのコンストラクターを一つ用意しなければなりませんが、 StreamWriterクラスは引数なしのコンストラクタを用意されていないため困っています。 自作クラス自身もFileクラスのラッパークラスで引数として使う必要があるため 継承関係を維持してVB6に公開する必要があります。 この問題をなんとか解決する手法って存在するのでしょうか? ちなみにほかに考えた手法は下記です。 ・プロパティーに StreamWriterのインスタンスを用いて継承関係なしであとでinitメソッドを呼び出す   →Fileラッパークラスの引数でStreamWriter型に代入出来ないため不可 ・StreamWriterを引数に取るメソッドの実装をあきらめる   →極力したくない ・StreamWriterラッパークラスの引数なしコンストラクタでStreamWriterクラスの引数ありコンストラクタを呼ぶ   →後でファイルのパスを指定する方法が見つからないため不可 他言語はそれなりにやってきたのでコンストラクターをあとで呼び出すなんて出来ないのはなんとなくわかるのですが何せ.NETを触り始めたのが最近なのでよろしくお願い致します。

  • コンストラクタの変数を別のコンストラクタで使えますか?

    いつも大変勉強にさせてもらってます。 C#・・というかプログラミング初心者です。 勉強はとにかくしているんですが、躓いてばかりです・・。 多分基本的なことだとは思うんですが、調べても、本を読んでもわからなかったので、ご教授願います。 public void Set_ComboBox(string ColumnNo, string ColumnName, object CmbName) { System.Windows.Forms.ComboBox Cmb_WK; Cmb_WK = (System.Windows.Forms.ComboBox)CmbName; Cmb_WK.DataSource = this.M_KIJITableAdapter.GetDataById_Hinmei().Copy(); Cmb_WK.DisplayMember = "sname"; Cmb_WK.ValueMember = "id"; string sname = Cmb_WK.SelectedValue.ToString(); string id = Cmb_WK.GetItemText(Cmb_WK.SelectedValue).ToString(); } private void KijiCmbBox1_SelectedIndexChanged(object sender, EventArgs e) { Console.WriteLine("商品名" + sname + "ID" + id); } 上のコンストラクタで作った sname と id を下のコンストラクタで使いたいのですが、publicだからそのまま書いても使えるかと思ったんですけど、エラーになります。 さらに以下のようにソースを付け足してみたのですが、System.StackOverflowExceptionがでてしまい困っています。 public string sname{ get { return sname; } set { sname = value; } } public string id { get { return id; } set { id = value; } } そもそもコンテキストが違うとアクセスできないということでしょうか? ご存知の方、よろしければ教えてください。

  • 実引数リストと仮引数リストの長さが異なります

    実引数と仮引数はあっているはずですが、次のエラーが出ます。どうしてでしょうか? ------エラー----------------------- java: クラス Itemのコンストラクタ Itemは指定された型に適用できません。 期待値: 引数がありません 検出値: java.lang.String,int,java.util.Date 理由: 実引数リストと仮引数リストの長さが異なります -------------------------------------------------- public class Main { public static void main(String[] args) { String name= "test"; int price = 0; Date date = new Date(); Item item = new Item(name,price,date);//コンストラクタ実引数 } } class Item{ String name; int price; Date date; void Item(String name, int price, Date date)//コンストラクタ仮引数 { this.name = name; this.price = price; this.date = date; } }

    • ベストアンサー
    • Java
  • コンストラクタのオーバーロードについて

    class loo{ //フィールドの定義 int sland; //コンストラクタの定義1 loo(){ this.sland = 28; } //コンストラクタの定義2 loo(int sland){ this.sland = sland; } //メソッドの定義 void ken(){ System.out.println(this.sland); } } //mainメソッド class kkk{ public static void main(String args[]){ ---------------------------------------------- loo lo = new loo(); lo.ken(); lo.ken(100); ---------------------------------------------- } } コンストラクタのオーバーロードについて、伺いたいことがありますので掲載致しました。 今回は、kenメソッドを用いて変数slandに入っている値を表示するプログラムを作りたいと思っています。 コンストラクタのオーバーロードを利用するわけですが、プログラム実行後に 28 100 という風な出力結果を得ようと、上記のようなプログラミングを実施しました。 しかし、いざコンパイルをかけると java:27: ken() (loo 内) を (int) に適用できません lo.ken(100); ~ というエラーが表示されてしまいます。 ----でかっこってある部分に問題があるのはわかっているのですが、思うように結果を得ることができない状況です。 また、----の部分を、 loo lo = new loo(100); lo.ken(); lo.ken(); と、書き換えると出力結果は 100 100 と表示され、28が表示されなくなってしまいます。 お手数ですが、ご教授の程お願い致します。

専門家に質問してみよう