C# Double Dispatch

using System;

namespace ConsoleApp3
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Animal a = new Cat();
            Animal a1 = new Cat();
            Animal b = new Dog();
            Animal b1 = new Dog();
            Animal c = new Mouse();
            Animal c2 = new Mouse();

            a.FindSamething(a1);
            a.FindSamething(b);
            a.FindSamething(c);
            Console.WriteLine();

            b.FindSamething(a);
            b.FindSamething(b1);
            b.FindSamething(c);
            Console.WriteLine();

            c.FindSamething(a);
            c.FindSamething(b);
            c.FindSamething(c2);
            Console.WriteLine();
        }

    }

    // 1. Cat, Dog 간 Double Dispatching 이 필요한 경우 구현 코드
    partial class Animal
    {
        public virtual void FindSamething(Animal animal) => Console.WriteLine("Animal FindSamething");

        public virtual void FindSamethingImpl(Cat obj) => Console.WriteLine("Animal-Cat FindSamethingImpl");
        public virtual void FindSamethingImpl(Dog obj) => Console.WriteLine("Animal-Dog FindSamethingImpl");
    }

    partial class Cat : Animal
    {
        public override void FindSamething(Animal animal)
        {
            animal.FindSamethingImpl(this);
        }

        public override void FindSamethingImpl(Cat obj) => Console.WriteLine("Cat-Cat = Same");
        public override void FindSamethingImpl(Dog obj) => Console.WriteLine("Cat-Dog = Cute");
    }

    partial class Dog : Animal
    {
        public override void FindSamething(Animal animal)
        {
            animal.FindSamethingImpl(this);
        }

        public override void FindSamethingImpl(Dog obj) => Console.WriteLine("Dog-Dog = Same");

        // 이렇게 리다이렉션 하는 경우 호출객체와 인자가 뒤바뀌기 때문에
        // this.FindSamethingImpl 와 obj.FindSamethingImpl 의 결과가 다른 경우에는 별도 구현해야함.
        public override void FindSamethingImpl(Cat obj) => obj.FindSamethingImpl(this);
        
    }






    // 2. Mouse가 추가된 경우 추가 구현 코드
    partial class Animal
    {
        public virtual void FindSamethingImpl(Mouse m) => Console.WriteLine("Animal-Mouse FindSamethingImpl");
    }
    partial class Cat
    {
        public override void FindSamethingImpl(Mouse m) => m.FindSamethingImpl(this);
    }

    partial class Dog
    {
        public override void FindSamethingImpl(Mouse m) => m.FindSamethingImpl(this);
    }

    partial class Mouse : Animal
    {
        public override void FindSamething(Animal animal)
        {
            animal.FindSamethingImpl(this);
        }

        public override void FindSamethingImpl(Cat c) => Console.WriteLine("Mouse-Cat = Mustache");
        public override void FindSamethingImpl(Dog d) => Console.WriteLine("Mouse-Dog = Four Legs");
        public override void FindSamethingImpl(Mouse m) => Console.WriteLine("Mouse-Mouse = Same");
    }

}

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다