본문 바로가기
C#

[C#] 인터페이스

by balhea 2024. 1. 12.

인터페이스(Interface)는 객체 지향 프로그래밍에서 클래스의 일종으로, 메서드의 시그니처(선언)만을 정의하고 실제 구현은 하위 클래스에서 이루어지도록 하는 추상화된 형태를 제공합니다. 인터페이스를 통해 여러 클래스가 동일한 메서드 시그니처를 공유하여 일관된 인터페이스를 제공할 수 있습니다. C#에서는 interface 키워드를 사용하여 인터페이스를 정의합니다.

 

인터페이스의 정의

public interface IDrawable
{
    void Draw(); // 메서드 선언만 가능하며, 구현은 하위 클래스에서 이루어짐
}

위의 예제에서 IDrawable 인터페이스는 Draw라는 메서드의 선언만을 가지고 있습니다. 구현은 이를 상속받는 클래스에서 이루어집니다.

 

인터페이스의 구현

public class Circle : IDrawable
{
    public void Draw()
    {
        Console.WriteLine("Drawing a circle");
    }
}

public class Square : IDrawable
{
    public void Draw()
    {
        Console.WriteLine("Drawing a square");
    }
}

위의 예제에서 Circle 및 Square 클래스는 IDrawable 인터페이스를 구현하고 있습니다. 이들 클래스는 Draw 메서드를 반드시 구현하여야 합니다.

 

인터페이스의 사용

class Program
{
    static void Main()
    {
        IDrawable shape1 = new Circle();
        IDrawable shape2 = new Square();

        shape1.Draw(); // 동적 바인딩에 의해 Circle 클래스의 Draw 메서드 호출
        shape2.Draw(); // 동적 바인딩에 의해 Square 클래스의 Draw 메서드 호출
    }
}

위의 예제에서 IDrawable 인터페이스를 사용하여 shape1과 shape2 변수를 선언하고, 각각 Circle과 Square 클래스의 인스턴스를 할당했습니다. 이를 통해 동일한 인터페이스를 공유하는 다양한 객체들을 동일한 방식으로 다룰 수 있습니다.

 

인터페이스의 장점

1. 다중 상속 구현: 여러 인터페이스를 하나의 클래스에서 구현할 수 있어 다중 상속을 흉내낼 수 있습니다.

2. 유연성과 확장성: 인터페이스를 통해 코드를 추상화하여 유연성과 확장성을 높일 수 있습니다. 클래스의 구조를 변경하지 않고도 새로운 기능을 추가할 수 있습니다.

3. 코드 재사용성: 인터페이스를 이용하면 동일한 메서드를 여러 클래스에서 재사용할 수 있습니다.

4. 표준화된 인터페이스 제공: 여러 클래스가 동일한 인터페이스를 구현하면 일관된 사용법을 제공하여 코드의 가독성을 높일 수 있습니다.

 

인터페이스는 객체 지향 프로그래밍의 핵심 원리 중 하나인 다형성을 구현하는 강력한 도구로 활용됩니다.

 

인터페이스의 상속

인터페이스도 클래스처럼 상속이 가능합니다. 이를 통해 여러 인터페이스를 묶어 새로운 인터페이스를 만들거나, 기존의 인터페이스를 상속받아 새로운 기능을 추가할 수 있습니다.

public interface IResizable
{
    void Resize();
}

public interface IShape : IDrawable, IResizable
{
    // IDrawable과 IResizable 인터페이스를 상속받아 새로운 인터페이스 정의
    // 추가적인 메서드나 프로퍼티를 선언할 수 있음
    void Rotate();
}

위의 예제에서 IShape 인터페이스는 IDrawable과 IResizable 인터페이스를 상속받아 새로운 인터페이스를 정의하고 있습니다. 이를 구현하는 클래스는 Draw, Resize, Rotate 메서드를 모두 제공해야 합니다.

 

명시적 인터페이스 구현

하나의 클래스가 여러 인터페이스를 구현할 때, 인터페이스의 메서드명이 충돌할 수 있습니다. 이런 경우에는 명시적 인터페이스 구현을 통해 충돌을 해결할 수 있습니다.

public interface IA
{
    void Method();
}

public interface IB
{
    void Method();
}

public class MyClass : IA, IB
{
    // 명시적 인터페이스 구현
    void IA.Method()
    {
        Console.WriteLine("IA.Method");
    }

    void IB.Method()
    {
        Console.WriteLine("IB.Method");
    }
}

위의 예제에서 MyClass는 IA와 IB 인터페이스를 구현하고 있습니다.

 

IA.Method와 IB.Method는 명시적으로 구현되어 있으며, 호출 시에는 인터페이스명을 통해 어떤 메서드를 호출할지 명시해야 합니다.

MyClass myClass = new MyClass();
((IA)myClass).Method(); // "IA.Method" 출력
((IB)myClass).Method(); // "IB.Method" 출력

 

인터페이스의 사용 예시: 컬렉션의 정렬

public interface IComparable
{
    int CompareTo(object obj);
}

public class Student : IComparable
{
    public string Name { get; set; }
    public int Age { get; set; }

    public int CompareTo(object obj)
    {
        if (obj is Student otherStudent)
        {
            // 학생을 나이 순으로 정렬
            return this.Age.CompareTo(otherStudent.Age);
        }
        throw new ArgumentException("Object is not a Student");
    }
}

위의 예시에서 IComparable 인터페이스는 객체를 비교하는 메서드 CompareTo를 정의하고 있습니다. Student 클래스는 IComparable을 구현하여 나이를 기준으로 학생을 정렬할 수 있습니다.

List<Student> students = new List<Student>
{
    new Student { Name = "Alice", Age = 25 },
    new Student { Name = "Bob", Age = 22 },
    new Student { Name = "Charlie", Age = 28 }
};

students.Sort();

List의 Sort 메서드는 내부적으로 IComparable을 구현한 객체들을 비교하여 정렬합니다. 위의 예제에서는 학생들을 나이 순으로 정렬하게 됩니다.

 

인터페이스는 코드의 일관성과 유연성을 제공하여 객체 간의 상호작용을 간편하게 만들어줍니다. 이를 통해 다양한 클래스가 동일한 인터페이스를 구현함으로써 일관된 패턴을 유지할 수 있습니다.

'C#' 카테고리의 다른 글

[C#] 추상 클래스  (0) 2024.01.12
[C#] 다형성  (0) 2024.01.12
[C#] 상속  (0) 2024.01.01
[C#] 캡슐화  (0) 2023.12.23
[C#] 클래스와 객체  (0) 2023.12.22