親インスタンスAが孫インスタンスCの値を取得したい
親インスタンスAが子インスタンスBを呼び、子Bが孫Cを呼び、というコードのとき、
孫Cが取得した値を、親Aにどう伝えるか色々と方法を考えたのでメモ。
具体的にコードでいうとこんな感じ
class Program { static void Main(string[] args) { Console.WriteLine("ObjAを呼びます\n"); ObjA obj = new ObjA(); obj.Execute(); // ここで objC の n を表示させたい } } class ObjA { // コンストラクタ public ObjA() { } public void Execute(){ Console.WriteLine("ObjAが呼ばれました\n"); Console.WriteLine("ObjBを呼びます\n"); ObjB obj = new ObjB(); obj.Execute(); } } class ObjB { // コンストラクタ public ObjB() { } public void Execute() { Console.WriteLine("ObjBが呼ばれました\n"); Console.WriteLine("ObjCを呼びます\n"); ObjC obj = new ObjC(); obj.Execute(); } } class ObjC { // コンストラクタ public ObjC() { } public void Execute() { Console.WriteLine("ObjCが呼ばれました\n"); Console.WriteLine("数値を入力してください > "); int n = int.Parse(Console.ReadLine()); // ここで n を Main に伝えてあげたい } }
引数で変数を参照渡ししまくる
class Program { static void Main(string[] args) { Console.WriteLine("ObjAを呼びます\n"); ObjA obj = new ObjA(); int number = 0; obj.Execute(ref number); // objA の n を表示させる Console.WriteLine(number.ToString() + "を入力しました\n"); } } class ObjA { // コンストラクタ public ObjA() { } public void Execute(ref int number){ Console.WriteLine("ObjAが呼ばれました\n"); Console.WriteLine("ObjBを呼びます\n"); ObjB obj = new ObjB(); // ObjB の値を objA に受け取る obj.Execute(ref number); } } class ObjB { // コンストラクタ public ObjB() { } public void Execute(ref int number) { Console.WriteLine("ObjBが呼ばれました\n"); Console.WriteLine("ObjCを呼びます\n"); ObjC obj = new ObjC(); // objC の値を objB に受け取る obj.Execute(ref number); } } class ObjC { // コンストラクタ public ObjC() { } public void Execute(ref int number) { Console.WriteLine("ObjCが呼ばれました\n"); Console.WriteLine("数値を入力してください > "); int n = int.Parse(Console.ReadLine()); // ここで n を ObjB に渡す number = n; } }
Execute メソッドの引数に、変数を参照渡しして、
C → B → A と値を引き継いでいく。
クラスのプロパティに値を保持しておく
class Program { static void Main(string[] args) { Console.WriteLine("ObjAを呼びます\n"); ObjA obj = new ObjA(); obj.Execute(); // objA の number プロパティを表示させる Console.WriteLine(obj.number.ToString() + "を入力しました\n"); } } class ObjA { // コンストラクタ public ObjA() { this.number = 0; } // プロパティ private int _number; public int number { get { return this._number; } set { this._number = value; } } public void Execute(){ Console.WriteLine("ObjAが呼ばれました\n"); Console.WriteLine("ObjBを呼びます\n"); ObjB obj = new ObjB(); obj.Execute(); // ObjB の number プロパティを ObjA の number プロパティに保存 this.number = obj.number; } } class ObjB { // コンストラクタ public ObjB() { this.number = 0; } // プロパティ private int _number; public int number { get { return this._number; } set { this._number = value; } } public void Execute() { Console.WriteLine("ObjBが呼ばれました\n"); Console.WriteLine("ObjCを呼びます\n"); ObjC obj = new ObjC(); obj.Execute(); // ObjC の number プロパティを ObjB の number プロパティに保存 this.number = obj.number; } } class ObjC { // コンストラクタ public ObjC() { this.number = 0; } // プロパティ private int _number; public int number { get { return this._number; } set { this._number = value; } } public void Execute() { Console.WriteLine("ObjCが呼ばれました\n"); Console.WriteLine("数値を入力してください > "); int n = int.Parse(Console.ReadLine()); // ここで n を ObjC の numberプロパティに保存 this.number = n; } }
ObjB.Execute が ObjC.number を参照 → ObjA.Execute が ObjB.number を参照と
値を一旦プロパティに保持して、親が子のプロパティを参照していく。
一番親のプロパティにセットする
class Program { // プロパティ public static int number; static void Main(string[] args) { Console.WriteLine("ObjAを呼びます\n"); ObjA obj = new ObjA(); obj.Execute(); // this.number プロパティを表示させる Console.WriteLine(Program.number.ToString() + "を入力しました\n"); } } class ObjA { // コンストラクタ public ObjA() { } public void Execute(){ Console.WriteLine("ObjAが呼ばれました\n"); Console.WriteLine("ObjBを呼びます\n"); ObjB obj = new ObjB(); obj.Execute(); } } class ObjB { // コンストラクタ public ObjB() { } public void Execute() { Console.WriteLine("ObjBが呼ばれました\n"); Console.WriteLine("ObjCを呼びます\n"); ObjC obj = new ObjC(); obj.Execute(); } } class ObjC { // コンストラクタ public ObjC() { } public void Execute() { Console.WriteLine("ObjCが呼ばれました\n"); Console.WriteLine("数値を入力してください > "); int n = int.Parse(Console.ReadLine()); // 一番親のProgramクラスにダイレクトに n を設定 Program.number = n; } }
C → B → A → Main とバケツリレーみたいに値を渡していくから面倒なのであって、
C → Main と直接渡してあげればいいじゃないかの例。
number が環境変数のような大域で使う値なら良いのかも。
デザインパターンっぽく
class Program { static void Main(string[] args) { Console.WriteLine("ObjAを呼びます\n"); ObjA obj = new ObjA(); obj.Execute(); // ここで objA の number を表示 Console.WriteLine(obj.number.ToString() + "を入力しました\n"); } } class BaseObj { private int _number; public int number { get { return this._number; } set { this._number = value; } } } class ObjA : BaseObj { // コンストラクタ public ObjA() { } public void Execute() { Console.WriteLine("ObjAが呼ばれました\n"); Console.WriteLine("ObjBを呼びます\n"); ObjB obj = new ObjB(); // n を ObjA にセット obj.Execute(this); } } class ObjB : BaseObj { // コンストラクタ public ObjB() { } public void Execute(BaseObj b_obj) { Console.WriteLine("ObjBが呼ばれました\n"); Console.WriteLine("ObjCを呼びます\n"); ObjC obj = new ObjC(); // n を ObjA にセット obj.Execute(b_obj); } } class ObjC : BaseObj { // コンストラクタ public ObjC() { } public void Execute(BaseObj b_obj) { Console.WriteLine("ObjCが呼ばれました\n"); Console.WriteLine("数値を入力してください > "); int n = int.Parse(Console.ReadLine()); // n を ObjA にセット b_obj.number = n; } }
Execute に ObjA 自身を渡してあげて、最終的に ObjC.Execute で ObjA.numberに値をセットする。
デザインパターンでこういう事例を見たが、何の事例だったか忘れた。
おしまい
今回は 孫C → 子B → 親A と値をバケツリレーしていったが、
逆に 親A → 子B → 孫C と値をリレーする場合も考えなくちゃ。