• ベストアンサー

C# クラスのインスタンスについて

クラス(ClassA)を作成した後に別のクラス(ClassB)内でClassAインスタンスを作成したとします。 このインスタンスをさらに別のクラス(ClassC)で使用したいと思うの ですが可能なんでしょうか? 要するに1つのインスタンスを他で使いまわすような事ができないの かなって思っています。 自分で調べると「Singletonパターン」という方法があるようですが 他の方法もあれば知ってみたいと思っています。 ※環境はWinXP、VS2005 C# です。 以上ですが、よろしくお願いいたします。

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

  • ベストアンサー
  • Xaval
  • ベストアンサー率58% (61/105)
回答No.3

>要するに1つのインスタンスを他で使いまわすような事ができないの かなって思っています。 >自分で調べると「Singletonパターン」という方法があるようですが >他の方法もあれば知ってみたいと思っています。 Singletonパターン[Gamma95] は、単一子インスタンスで、排他制御などをする場合に使います。 一つのクラスでロックフラグを立てたりとかが容易ですよね? 単純にstaticクラスを作らなかったことは正解です。 インスタンスクラスであれば、これからいろんなパターンに派生していきますので。 その他の使い回しのパターンは、Singletonを応用しているものが多いですので、それだけで十分です。 それとも、別にClassAインスタンスは複数作ってもいいが、とりあえずあるところでできたやつを別のところで使う、と言うことでしょうか? 普通に外部からアクセス可能にして、それを使えばよいのですが。。 ちょっと設計的な話になりますが、考え直した方が良いです。 オブジェクト指向の基本原理として ・変更に対してはクローズに ・拡張に対してはオープンに というのがあります。 あるクラス内部で生成したインスタンスが、他で使うと言うことは、 処理や状態的に関連がある場合です。 外部生成したものを突っ込むことはありますが。 無いわけじゃないし、必要に応じてそうなります。詳しいことは知らないので何とも言えませんが、 せっかくデザインパターンに触れたので、すべて見てみてください。 なお、No1,2に補足しますが、VisualStudio2008なら、  public string Name{get; set;} でOKです。

19820202
質問者

お礼

Xaval様 詳しい解説、またオブジェクト指向の考え方も教えていただきありがとうございます。 >とりあえずあるところでできたやつを別のところで使う、と言うことでしょうか? 今回の私のやりたかった処理はこれでした。 >オブジェクト指向の基本原理として >・変更に対してはクローズに >・拡張に対してはオープンに あまり意識はしていなかったのでありがたい情報でした。 今回は本当にありがとうございました。

その他の回答 (2)

  • sgwjn
  • ベストアンサー率70% (47/67)
回答No.2

#01の方のサンプルで質問の要件は満たしていると思いますが、せっかくC#を使うのですから、SetterとGetterはプロパティを使用した方が良いような気がします。 public string Name {  set  {   this.name = value;  }  get  {   return this.name;  } }

19820202
質問者

お礼

sgwjn様 プロパティは使用するようにします。 まだまだ、C#は経験が浅いので1つ1つの情報がありがたいです。 今回はありがとうございます。

  • Splatter
  • ベストアンサー率41% (181/440)
回答No.1

クラスのインスタンスを渡してあげることで、 そのインスタンスを別のクラスで使用することができます。 以下に簡単な例を示します。 ClassA(パラメータとGetter、Setterだけ持つものとします) ------------------------------------------------------ private string name; // 名前 // コンストラクタ public ClassA() { } // 名前を取得する public string getName() { return name; } // 名前を設定する public void setName(string name) { this.name = name; } ------------------------------------------------------ このClassAは内部にnameというパラメータを持ち、 外部からgetName()を実行するとnameの値を返し、 外部からsetName()を実行するとnameの値を記憶します。 ClassB(ClassAのインスタンスを後述のClassCへ渡します) ------------------------------------------------------ // テスト用のメソッド private void Test() { // ClassAのインスタンスを生成する ClassA classA = new ClassA(); // ClassCのメソッドを実行する classA = ClassC.YamadaTarou(classA); // classAのnameの内容を表示する MessageBox.Show(classA.getName()); } ------------------------------------------------------ ClassBではClassAのインスタンスを生成していますね。 この時点ではclassAの中のnameパラメータはnullです。 その後、このclassAをClassCのYamadaTarouメソッドに渡し、 結果として帰ってきたclassAを再び受け取っています。 最後に、classAのnameの値をメッセージ表示させています。 ClassC(classAを受け取り、名前をセットして返します) ------------------------------------------------------ public ClassA YamadaTarou(ClassA classA) { // 受け取ったclassAに、名前をセットします classA.setName("山田太郎"); // 処理結果(classA)を返します return classA; } ------------------------------------------------------ 以上のように、通常の変数と同じようにクラスのインスタンスも 渡すことが可能です。上記例は単純に別クラスで内容のセットを しているだけですが、ここに計算結果を入れたり、パラメータに 応じて以降の処理を分岐したり、といった事にも使えますね。

19820202
質問者

お礼

Splatter様 丁寧な解説本当にありがとうございます。 サンプルを拝見して考え方が理解できました。 >通常の変数と同じようにクラスのインスタンスも渡すことが可能 この扱いがポイントですね。自分のイメージ通りの処理ができました。

関連するQ&A

  • 条件によって別のクラスのインスタンスを作成する場合

    大きな条件分岐があって、その条件によって別のクラスを同じ名前でインスタンス化し、以降で使いたいのですが、うまくコンパイルが通りません。考えてみればifブロックの中だけで有効なインスタンスになってしまうので、当たり前かも知れません。どのようにすれば、使えるようになるのでしょうか。 以下にコードを載せます。正しい書き方を教えて下さい。 よろしくお願いします。 if(条件A){ classA object; // objectという名前でclassAをインスタンス化 }else{ classB object; // objectという名前でclassAとは別のclassBをインスタンス化 } object.methodA(); // objectのmethodA関数を使用したい

  • [Obj-c]元クラスからサブクラスのメソッド

    Objective-Cの勉強をしています。 ClassAは元クラス(スーパークラス)です、 ClassB1、B2はClassAを継承(サブクラス)しています。 ClassAとClassB1にはiMethodというメソッドが存在します。 最下部にソースと実行結果があります。 ●そこで質問なのですが、  ClassAのインスタンスにClassB1のインスタンスをセットすると、  同じ名前のメソッドがあるだけでなぜClassB1のメソッドが呼ばれるのでしょうか?  (下記ソースの[bangai iMethod]; の部分です。)  ClassB1のインスタンスを渡すとClassAのインスタンスが  ClassB1のメソッドを使用できる理由がわかりません、  継承しているとはいえ型が違うものを参照渡しできる理由も今ひとつわからないです。  またこれはどういう機能を言うのでしょうか?  (例えば ポリモーフィズム、動的バインディングなど) ★ソース ------------------------------------------------------------------------------ #import <Foundation/Foundation.h> // ClassA @interface ClassA : NSObject { } @end @implementation ClassA -(void) iMethod { NSLog(@"スーパークラスのインスタンスメソッドです。\n"); return; } @end // ClassB1 @interface ClassB1 : ClassA @end @implementation ClassB1 -(void) iMethod { NSLog(@"サブクラスのインスタンスメソッドです。\n"); return; } @end // ClassB2 @interface ClassB2 : ClassA @end @implementation ClassB2 @end int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... ClassB1 *instance_B1 = [[ClassB1 alloc]init]; ClassB2 *instance_B2 = [[ClassB2 alloc]init]; [instance_B1 iMethod]; [instance_B2 iMethod]; // 親には子のクラスが入れられる ClassA *bangai = instance_B1; [bangai iMethod]; } return 0; } ------------------------------------------------------------------------------ ★実行結果 サブクラスのインスタンスメソッドです。 スーパークラスのインスタンスメソッドです。 サブクラスのインスタンスメソッドです。

  • 配列であるメンバのコンストラクタを呼ぶ方法

    C++のクラスについて教えていただけないでしょうか。以下のような場合、 class ClassA {   int A; public:   ClassA(int a): A(a) {} }; class ClassB {   ClassA A; public:   ClassB(): A(10) {} }; class ClassC {   ClassA A[2]; public:   ClassC() {} //配列であるメンバのコンストラクタを呼び出したい }; ClassBがClassAのコンストラクタを呼ぶには上記のような方法で良いと思うのですが、ClassCのようにメンバが配列の場合、そのメンバのコンストラクタを呼ぶにはどのようにしたら良いのでしょうか。ご教授をお願いします。

  • 同一クラスインスタンス名で別クラスのインスタンス作成方法(C++)

    下記ソース(Java)の処理をするような、C++の実装方法を教えていただきたいです。 【処理内容】 クラスBのインスタンスを保持しており、クラスBのインスタンス名と同一であるクラスAのインスタンス生成 ClassA A_Instance = (ClassA)Class.forName(B_instance.name).newInstance(); 要はクラスインスタンスの名前の求め方がわからないのです。それさえわかれば、newしてクラスポインタを返すメソッドを用意すれば何とかなると考えていますが。 ※C++のAPI一覧はどこにあるのだろうか・・・

  • 親クラスのフリをした子クラスの使い方を教えて下さい

    以前、QNo.3479089でお世話になった者です。類似というか、続きの質問です。 ClassAを継承するClassBがあり、条件によって、ClassAまたはClassBをインスタンス化して使います。 (ClassBは、ClassAのメソッドの一部をオーバーライドして、ClassB固有のメソッドも追加しています) ClassA* pObj = NULL; if( ある条件 ) {   pObj = new ClassA(); } else( その他の条件 ) {   pObj = new ClassB(); } pObj->common_method(); これが常套手段と伺ったのですが、ClassBがインスタンス化された場合、ClassB固有のメソッドmethodBを呼び出そうとすると、「ClassAにはmethodBが存在しない」といったようなコンパイルエラーが出ます。 pObj->methodB(); // ここで、エラー それで、エラーを解消するために、「その他の条件」の時に、dynamic_castを使ってみました。 if( その他の条件 ) {   ClassB* pObj2 = dynamic_cast<ClassB*>( pObj );   pObj2->methodB(); } 上記でコンパイルエラーは解消したのですが、なにか、非常にめんどくさいです。 また、ClassAのフリをした実体ClassBを使っているのだから、オーバーライドしているメソッドもdynamic_castをしないと呼び出されないような気がします。 結局、親のフリした子クラスを作成する場合、こんなにめんどくさいことをしないといけないのでしょうか? それともこのやり方はおかしいですか? この場合、どういうふうにするものなのか、教えて下さい。よろしくお願いします。

  • (クラス名.this.メソッド)って・・・?

    次のようなクラスで public class ClassA {   public static void main(String[]args)   {     new ClassA(); /* 構築A */   }   public ClassA()   {     new ClassI();   }   public class ClassI()   {     ClassA.this.MethodA(); /* 命令A */   }   public void MethodA()   {     System.out.println("HELLO");   } } この命令Aの部分の (クラス名.this.メソッド)というアクセス方法がよくわかりません とりあえす(ClassA.this)が構築Aの部分で生成された インスタンスではないかとおもうのですがそれで正しいのでしょうか? また インナークラスはインナークラスの定義されているクラス以外から インスタンスを生成できないのでしょうか? つまり次のクラスを追加して public class ClassB {   public ClassB()   {     new ClassA.ClassI(); /* 構築B */   } } ここの構築Bのように(この場合はダメの様ですが)他のクラスから 構築することです もし仮にできるとしたら そのときの命令Aの(ClassA.this)は一体なんの インスタンスを指すのでしょうか 急ぎのプログラムを作っているので たいへん不躾ですが、なるべく早くお答えをお願いします

    • ベストアンサー
    • Java
  • 参照メンバを持つクラス

    ClassAとClassBにCMyDataオブジェクトを渡したいのですが、メモリ上に同じデータのコピーを作りたくないので、コンストラクタがCMyDataの参照を受け取る設計にしました。こうすることで、CMyDataの実体はメモリ上に1つしか存在しないことになります。 ただ、クラスが、自身が管理していない外部領域にあるデータへの参照を使って仕事をするというのに違和感を感じます。 完全コンストラクタというデザインパターンがあって、クラスのインスタンスを生成する時に必要な全てのデータを渡すのが正しい流儀だそうです。 しかしこのClassA(B)の設計では、ClassA(B)の寿命が終わるまで参照先のデータが生きているとは限りません。もっといい設計はないでしょうか?ちなみにCMyDataは実際にはかなり大きなデータで、一時的であってもコピーを複数持ちたくないのです。ClassAとClassBは、実際は他のデータも参照するため1つのクラスにはしたくないのです。 class CMyData { // 色々なデータ }; class CMain { CMyData* myData; // ファイルからデータを読み込んで生成 ClassA* objA; ClassB* objB; void ReadFile() { myData = new CMyData(); // ファイルからデータを読み込みCMyData構築 } void Init() { ReadFile(); objA = new ClassA(*myData); // 自身のメンバ変数の参照でClassAを構築 objB = new ClassB(*myData); } void DoProcess() { Init(); // 実行は一度だけ objA->hoge(); // ClassAに仕事をさせる objB->foo(); // ClassBに仕事をさせる } } class ClassA { CMyData& m_data; public: ClassA(CMyData& data) m_data=data; // CMyDataオブジェクトを参照で受け取る void hoge(); } class ClassB { CMyData& m_data; public: ClassB(CMyData& data) m_data=data; // CMyDataオブジェクトを参照で受け取る void foo(); }

  • 継承元クラスのプロパティを参照する手段

    お世話になります。 ActionScrip3に関する質問です。 現在、カスタムクラスを勉強しております。 外部クラスでClassA、ClassBを作成し、 ClassAにある処理の途中でClassBを実行し、ClassBの中からClassAのプロパティを参照しにいく 処理を行いたいと思い、ClassBのコンストラクタからClassAのプロパティをtraceしました。 プロパティppt2は「かきくけこ」が出力されましたが、ppt1は「null」になってしまいました。 恐らく、タイムラインからClassAに対して設定したプロパティの値は見にいけていないようですが、 タイムラインから設定したプロパティの値を継承したClassBから参照しにいく方法はありますでしょうか? 下記ソースと同じ方法でなくても結構ですので、タイムラインから設定した スーパークラスのプロパティ値をサブクラスから参照・変更できる方法を ご教授いただければと存じます。 お手数ではありますが、宜しくご教授ください。 宜しくお願いいたします。 /* タイムライン側の処理 -----------------------*/ var test:ClassA = new ClassA(); test.ppt1 = "あいうえお"; test.goNext(); /* ClassAの処理 -----------------------*/ package {  // インポート記述は省略  public class ClassA {   var ppt1:String;   var ppt2:String = "かきくけこ";   // コンストラクタ   public function ClassA() { }   public function goNext():void {    var classb:ClassB = new classB();   }  } } /* ClassBの処理 -----------------------*/ package {  // インポート記述は省略  public class ClassB extends ClassA {   // コンストラクタ   private function ClassB() {    trace(ppt1);    trace(ppt2); }  } }

    • ベストアンサー
    • Flash
  • クラスでnew宣言

    いつも御世話になっています。 クラス作成時に、 オブジェクト型(クラス型)を変数として宣言している時がある気がするのですが、ClassB classB = new ClassB(); この場合の利点は何かあるのでしょうか? 普通に考えれば、この記述を宣言することで、この宣言がされているクラス自身が、ClassBの実体を持つことになり、このクラスだけで多数のクラスの実体を利用できるようになる。 と思ったのですが。 クラスとしては、 ClassA { private ClassB classB = new ClassB(); } という場合です。 ここで、private ClassB classB;でない理由: むやみに、上記の書き方をすると、外部から書き換えられてしまう恐れがあるから、、なるべくその可能性を回避するため 宜しくお願いします。

    • ベストアンサー
    • Java
  • Rails AR 深い階層のテーブル参照

    Rails ActiveRecord において、 深い階層のテーブルを参照するのに有効な方法はないでしょうか? 例:下記の構造で classD から classAのnameを取得する。 classA  1→n  classB  1→n  classC  1→n  classD □classA   id   name □classB   id   name   class_a_id □classC   id   name   class_b_id □classD   id   name   class_c_id #前提条件 classC, classB, classAが必ずしも存在するとは限らない。 classDからclassAを参照する際に、#前提条件にあるように、 classB or classCが存在しない(nil)場合、 > class_d.class_c.class_b.class_a.name とするとエクセプションが発生しますが、 これを回避するために、 if class_d.class_c and class_d.class_c.class_b and class_d.class_c.class_b.class_a class_d.class_c.class_b.class_a.name end のようにしていますが、煩わしくてしかたがありません。 実際はエラーログ出力等行っているため、さらに複雑な処理になっています。 もっとスマートなコーディング方法やアドバイスがありましたら宜しくお願いします。 #補足 (1) has_many :through を使ってショートカットが作れることを知りましたが、 今回の例のように、複数階層となる場合の記述方法がわかりません。 ご存知の方回答お願いいたします。 (2) そもそも前提条件に問題があるのではないかとも思っています。 前提条件にあるような状態にならない様な仕組みにする、 もしくは、そのような状態にならないよう管理する、等すべきでしょうか? 以上宜しくお願いいたします。

    • ベストアンサー
    • Ruby

専門家に質問してみよう