C#에서 인터페이스(Interface)는 속성(Property), 메서드(Method), 이벤트(Event) 같은 멤버들을 정의하는 일종의 계약(Contract) 역할을 합니다. 인터페이스에는 멤버의 선언만 포함될 뿐 실제 구현 코드는 없으며, 구체적인 기능 구현은 해당 인터페이스를 상속받는 클래스의 책임입니다.
추상 클래스(Abstract Class)도 어느 정도 비슷한 목적으로 사용되지만, 주로 기반 클래스에서 일부 메서드만 선언해 두고 나머지 구체적인 기능은 파생 클래스가 구현하도록 설계할 때 활용됩니다.
인터페이스와 추상 클래스의 주요 차이점
- 다중 상속 가능 여부: 하나의 클래스는 여러 개의 인터페이스를 동시에 상속(구현)할 수 있지만, 추상 클래스는 단 하나만 상속할 수 있습니다.
- 다중 상속 구현 방식: 추상 클래스로는 다중 상속을 구현할 수 없으며, 인터페이스를 사용해야만 다중 상속의 효과를 얻을 수 있습니다.
- 필드(Field) 정의: 인터페이스 내부에는 필드를 정의할 수 없지만, 추상 클래스에서는 필드를 자유롭게 선언하고 사용할 수 있습니다.
- 접근 한정자(Access Modifier): 인터페이스에는 public, private, protected, internal 같은 접근 한정자를 지정할 수 없습니다. 인터페이스의 모든 멤버는 기본적으로 public으로 처리됩니다.
그렇다면 어떤 것을 선택해야 할까?
인터페이스가 적합한 경우
서로 다른 클래스들에게 특정 동작을 반드시 수행하도록 강제하고 싶거나, 하나의 클래스가 여러 역할을 동시에 가져야 할 때 인터페이스가 가장 적합합니다. 예를 들어 IComparable, IDisposable처럼 특정 기능의 약속을 정의하는 데 널리 사용됩니다.
추상 클래스가 적합한 경우
여러 파생 클래스가 공통으로 사용하는 필드, 생성자, 이미 구현된 메서드 등을 공유해야 할 때는 추상 클래스가 유리합니다. 공통 로직은 기반 클래스에 두고, 클래스마다 달라져야 하는 부분만 추상 메서드로 선언하여 파생 클래스에서 구현하면 됩니다.