[C# 객체지향] 타입 유형 확장3_인터페이스

eunjin lee·2022년 6월 27일
0

C# 9.0 프로그래밍

목록 보기
11/50


1. 특징

  • 인터페이스는 구현 없는 메서드 선언만을 갖고 있다.
  • 추상 클래스와 비슷하지만, 클래스는 다중 상속이 불가능하고 인터페이스는 가능하다.
  • 인터페이스로부터 구현해야 하는 메서드의 접근 제한자는 public이여야 하며, override 예약어를 지정하지 못한다. (굳이 그럴 필요가 없기 때문에)
    ✍ 샘플 코드
    namespace Pjt
    {
         interface Machine
        {
            //int var; //컴파일 에러. 필드가 포함될 수 없음.
            int Var { get; set; } // 프로퍼티는 메서드이므로 포함될 수 있음.
            void Work();
            void Stop(int var);
        }

        class Computer : Equipment, Machine
        {
            public int Var { get; set; }

            public void Stop(int var) //public이어야 한다. private으로 바꾸면 컴파일 에러.
            {
                Console.WriteLine("Stopped at "+var);
            }

             void Machine.Work() //인터페이스를 명시하면 접근 제한자를 생략할 수 있지만, 생략되었다고 private은 아니다.
            {
                Console.WriteLine("Working...");
            }

        }

        class Equipment
        {
            virtual public void Installed()
            {
                Console.WriteLine("Installed");
            }
        }

        class Test
        {
            static void Main(string[] args)
            {
                Computer machine1 = new Computer();
                machine1.Stop(10);
                // machine1.Work(); 컴파일 에러. 인터페이스명을 명시한 메서드는 인터페이스의 멤버에 종속되어 Machine의 멤버로 호출이 불가능하다.
                machine1.Installed();

                Machine machine2 = machine1 as Machine;
                machine2.Stop(3);
                machine2.Work();
                //machine2.Installed(); 컴파일 에러. 인터페이스는 Installed에 대한 정보가 없다.
            }
        }
    }

✅ 결과

  Stopped at 10
  Installed
  Stopped at 3
  Working...


2. 용도

  • 다형성
    ✍ 샘플 코드
    interface IDrawingObject
    {
        void Draw();
    }

    class Triangle : IDrawingObject
    {
        public void Draw()
        {
            Console.WriteLine("Draw Triangle.");
        }
    }

    class Square : IDrawingObject
    {
        public void Draw()
        {
            Console.WriteLine("Draw Square.");
        }
    }

    class Test
    {
        static void Main(string[] args)
        {
            IDrawingObject[] instances = new IDrawingObject[] {new Triangle(), new Square()};
            foreach (IDrawingObject instance in instances)
            {
                instance.Draw();    
            }
        }
    }

✅ 결과

Draw Triangle.
Draw Square.
  • 암시적인 계약
    ✍ 샘플 코드
    interface IDrawingObject
    {
        void Draw();
    }

    class Universe
    {

    }

    class Triangle : IDrawingObject
    {
        public void Draw()
        {
            Console.WriteLine("Draw Triangle.");
        }

        public override string ToString()
        {
            return "a,b,c";
        }
    }

    class Square : IDrawingObject
    {
        public void Draw()
        {
            Console.WriteLine("Draw Square.");
        }

        public override string ToString()
        {
            return "a,b,c,d";
        }
    }

    class Test
    {
        static void Main(string[] args)
        {
            Object[] objects = new Object[] {new Triangle(), new Square(), new Universe()};

            foreach(object o in objects)
            {
                if(o is IDrawingObject)
                {
                    Console.WriteLine(o.ToString());
                }
            }

        }
    }

✅ 결과

    a,b,c
    a,b,c,d

특정 메서드를 재정의한 클래스만을 구분할 수 있다. 한마디로, 인터페이스는 자유롭게 정의할 수 있는 계약인 것이다.

  • 콜백
    ✍ 샘플 코드
    class Test
    {
        static void Main(string[] args)
        {
            Caller c = new Caller();
            c.Work();
        }
    }

    interface ICaller
    {
        void callBack(); //콜백용 메서드를 인터페이스로 분리한다.
    }
    class Caller : ICaller
    {
        public void Work()
        {
            Console.WriteLine("Caller Class Do Its Business...");
            CalledClass c = new CalledClass();
            c.Work(this);
        }

        public void callBack()
        {
            Console.WriteLine("Called Backed");
        }
    }

    class CalledClass
    {
        public void Work(ICaller caller)
        {
            Console.WriteLine("Called Class Do Its Business...");
            caller.callBack();//콜백 메서드 호출
        }
    }

✅ 결과

    Caller Class Do Its Business...
    Called Class Do Its Business...
    Called Backed

인터페이스로 콜백 vs 델리게이트로 콜백
인터페이스는 하나의 타입에 여러 메서드 계약을 담을 수 있어 더 편리하다. 그러나 델리게이트는 콜백 메서드를 다중으로 등록할 수 있다는 장점이 있다.


3. 예시

  • System.Array와 string 타입은 IEnumerable 인터페이스를 구현하여 foreach 구문을 사용할 수 있다.

0개의 댓글