반응형

✅ 인터페이스란 무엇인가요?

객체지향 프로그래밍을 공부하면서 인터페이스는 정말 많이 등장하는 개념이다.
클래스와 비슷해 보이지만, 사용하는 목적이 분명히 다르다.
이번 글에서는 인터페이스의 개념부터 왜 필요한지, 어떻게 사용하는지까지
예제와 함께 하나씩 정리해보려고 한다.


📌 다중 상속이 왜 위험한가요?

C#은 클래스 간의 다중 상속을 허용하지 않는다.
그 이유는 대표적으로 아래와 같은 문제가 있기 때문이다.

🧱 1. 다이아몬드 문제(Diamond Problem)

  • A → B, A → C, B와 C → D 를 상속받으면
  • A의 멤버가 D에 중복 상속되어 어떤 걸 써야 하는지 모호해진다.
  • 이런 모호성을 해결하려다 보면 코드가 더러워진다 😵

🔀 2. 복잡한 상속 구조

  • 여러 클래스를 동시에 상속받으면 클래스 간 관계가 꼬인다.
  • 디버깅, 유지보수, 확장이 어려워진다.

🔧 3. 이름 충돌 발생

  • 같은 이름의 멤버가 두 부모 클래스에 있을 때,
  • 어떤 걸 써야 하는지 애매해지고 충돌 처리 코드가 필요하다.

🧘‍♂️ 4. C#의 선택: 단일 상속 + 인터페이스

  • C#은 클래스는 단일 상속만 허용하고, 인터페이스는 다중 구현 가능하게 설계했다.
  • 덕분에 클래스 구조는 깔끔하게 유지하고, 다형성은 인터페이스로 처리할 수 있다!

🎯 그래서 인터페이스가 등장합니다

인터페이스는 쉽게 말하면 **“해야 할 일 목록(To-Do List)”**를 만드는 것과 같다.

public interface IMovable
{
    void Move(int x, int y);
}

이 인터페이스를 어떤 클래스가 "구현한다"고 선언하면, 반드시 안에 정의된 기능을 직접 만들어야 한다!

public class Player : IMovable
{
    public void Move(int x, int y)
    {
        // 플레이어 이동 구현
    }
}

🔄 인터페이스는 다중 구현이 가능하다!

public interface IUsable { void Use(); }
public interface IDroppable { void Drop(); }

public class Item : IUsable, IDroppable
{
    public void Use() { ... }
    public void Drop() { ... }
}

이렇게 클래스 하나에 여러 개의 인터페이스를 동시에 붙일 수 있다.
이건 다중 상속은 아니지만, 다중 상속처럼 여러 기능을 "약속"하고 "구현"하는 구조다!


🆚 인터페이스 vs 추상 클래스

항목 인터페이스 추상클래스
상속 가능 수 여러 개 (다중 구현) 하나만 (단일 상속)
구현 포함 여부 메서드 구현 불가 (.NET 5 이전 기준) 일부 구현 가능
목적 동작 명세 (계약) 공통 기능 제공
결합도 낮음 (느슨한 연결) 높음 (강한 연결)
 

✅ 정리하자면…

  • 인터페이스는 계약이다. "이 기능 반드시 구현해!"라는 강제성이 있다.
  • C#에서는 클래스 간 다중 상속을 피하고, 인터페이스를 통해 다형성을 구현한다.
  • 인터페이스를 사용하면 유지보수가 쉬운 구조, 유연한 설계가 가능해진다.

 

 

✅ 열거형 (enum) - 의미 있는 상수 만들기

프로그래밍을 하다 보면 의미 있는 상수 값들을 자주 다루게 된다.
예를 들어, 요일을 숫자로 0~6으로 다루는 것보다 Monday, Tuesday 같은 이름으로 다루는 게
훨씬 가독성도 좋고 실수도 줄일 수 있다.

이럴 때 등장하는 게 바로 **열거형(enum)**이다!


📌 열거형이란?

  • 열거형(enum)은 관련된 상수들의 집합이다.
  • 각 상수는 내부적으로 정수 값을 갖는다.
  • 열거형을 사용하면 코드가 가독성 있고 의미 있게 바뀐다.
enum DaysOfWeek
{
    Sunday,    // 0
    Monday,    // 1
    Tuesday,   // 2
    Wednesday, // 3
    Thursday,  // 4
    Friday,    // 5
    Saturday   // 6
}

위와 같이 선언하면, Monday는 내부적으로 1이라는 값을 가진다.


🎯 왜 열거형을 사용할까?

  1. 가독성 증가
    → if (day == 1) 보다 if (day == DaysOfWeek.Monday)가 훨씬 명확하다!
  2. 코드 실수 방지
    → 상수 값을 마음대로 입력하는 실수를 막을 수 있다.
  3. 코드 유지보수 편리
    → 의미 있는 이름으로 값들을 표현하면 추후 수정이 쉬워진다.

🛠️ 열거형 기본 사용법

🔹 열거형 선언

enum GameState
{
    MainMenu,
    Playing,
    Paused,
    GameOver
}

🔹 변수 선언과 사용

GameState state = GameState.Playing;

if (state == GameState.Paused)
{
    Console.WriteLine("게임이 일시정지되었습니다.");
}

🔹 열거형 → 정수형 형변환

int value = (int)GameState.Playing; // 결과: 1

🔹 정수형 → 열거형 형변환

GameState state = (GameState)2; // Paused

⚠️ 열거형에서 주의할 점

  • 열거형은 내부적으로 int형 정수값을 갖는다.
    따라서 정수값으로 캐스팅할 수 있지만, 정의되지 않은 값도 캐스팅은 되므로 주의해야 한다.
GameState state = (GameState)100;
Console.WriteLine(state); // 출력은 되지만 실제로는 존재하지 않는 값

✅ switch문과 함께 사용하기

switch (state)
{
    case GameState.MainMenu:
        Console.WriteLine("메인 메뉴입니다.");
        break;
    case GameState.Playing:
        Console.WriteLine("게임을 플레이 중입니다.");
        break;
    case GameState.Paused:
        Console.WriteLine("일시정지 상태입니다.");
        break;
    case GameState.GameOver:
        Console.WriteLine("게임 오버입니다.");
        break;
}

enum은 switch문에서 진짜 자주 쓰인다! 실수 없이 명확한 분기 처리가 가능해져서 정말 유용하다.


🧪 실습 예제: 월(Month) 처리하기

public enum Month
{
    January = 1,
    February,
    March,
    April,
    May,
    June,
    July,
    August,
    September,
    October,
    November,
    December
}

void PrintMonthName(int month)
{
    if (month >= 1 && month <= 12)
    {
        Month m = (Month)month;
        Console.WriteLine($"선택한 월은 {m}입니다.");
    }
    else
    {
        Console.WriteLine("잘못된 월입니다.");
    }
}

✨ 마무리하며

처음엔 그냥 숫자 쓰면 되지 싶었는데,
막상 열거형을 쓰고 나면 가독성, 실수 방지, 유지보수 모든 면에서 장점이 크다.
특히 게임 상태, 방향, 아이템 등 명확한 상태 구분이 필요한 경우에 정말 자주 쓰인다.

이번 정리로 다음 코딩부터는 잘 써보자!

반응형