読者です 読者をやめる 読者になる 読者になる

まるまるこふこふ

数々の次元が崩壊し、全ての生命が塵と化すのを見てきた。私ほどの闇の心の持ち主でも、そこには何の喜びも無かった。

親インスタンス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 と値をリレーする場合も考えなくちゃ。