인터페이스 정의 및 특징
인터페이스(Interface)는 C# 언어 객체 지향에서 클래스가 구현해야 하는 기능(행위)의 집합을 정의하는 참조 타입으로, 다중 상속의 문제를 피하면서 다형성을 실현하는 핵심이다.
| 구분 | 설명 |
|---|---|
| 정의 | 클래스나 구조체가 반드시 구현해야 할 메소드, 속성, 이벤트 등의 멤버를 선언만 해놓은 설계도이다. |
| 타입 분류 | 참조 타입 |
| 특징 | 1. 추상 멤버만 가질 수 있다.(C# 8.0 이전) 2. 모든 멤버는 기본적으로 public 이며, 접근 지정자를 명시할 수 없다. 3. 필드를 가질 수 없다. |
| 목적 | 표준화(규격 정의) 및 느슨한 결합을 통한 시스템 설계 |
인터페이스 선언
인터페이스의 이름은 관례적으로 대문자 I로 시작한다.
선언에 대한 예제 코드는 다음과 같다.
public interface ILogger
{
// 본문 없이 선언만 한다.
void LogMessage(string message);
int messageCount { get; set; }
}
클래스나 구조체는 인터페이스를 상속받아 모든 멤버를 반드시 구현해야 하며, 예제 코드는 다음과 같다.
public class FileLogger : ILogger // 인터페이스 상속
{
private int count = 0;
// 메소드 구현
public void LogMessage(string message)
{
// 아무 내용 구현
}
// 속성 구현
public int MessageCount
{
get { return count; }
set { count = value; }
}
}
인터페이스가 인터페이스를 상속받으면, 해당 인터페이스를 구현하는 클래스는 하위 인터페이스의 멤버까지 모두 구현해야 하며, 예제 코드는 다음과 같다.
public interface IReader { void Read(); }
public interface IWriter { void Write(); }
// IReadWrite는 IReader와 IWriter의 모든 멤버를 포함한다.
public interface IReadWrite : IReader, IWriter { }
클래스는 하나의 클래스만 상속받을 수 있지만, 다수의 인터페이스는 콤마(,)를 사용하여 동시에 구현할 수 있다.
// Printer 클래스는 IDevice와 IPrintable의 모든 멤버를 구현해야 한다.
public class Printer : IDevice, IPrintable
{
// 모든 IDevice 및 IPrintable 멤버 구현
}
추상 클래스와의 차이점
추상 클래스(Abstract Class)와 인터페이스 모두 추상화를 제공하지만, 그 목적과 허용되는 구성 요소에는 큰 차이가 있다.
| 구분 | 인터페이스 | 추상 클래스 |
|---|---|---|
| 역할 | 규격 정의(What), 다중 상속을 통한 다형성 실현 | 기능 확장(How), 공통 기능을 제공하는 템플릿 역할 |
| 멤버 허용 | (C# 8.0 이전)추상 멤버만 가지며, 필드를 가질 수 없다. | 일반 필드, 메소드 등을 가질 수 있다. |
| 상속 | 클래스는 다중 구현 가능 | 클래스는 단일 상속만 가능 |
| 접근 지정자 | (명시 불가능한)public | 멤버에 public, private 등 사용 가능 |
| 생성자 | 가질 수 없다. | 가질 수 있다. 단, 직접 인스턴스 생성은 불가능하다. |
C# 8.0 이후의 인터페이스 변화
C# 8.0부터 추상 클래스와의 경계가 모호해졌다.
-
기본 구현 메소드: 인터페이스 내에서 추상 메소드가 아닌 구현된 메소드를 가질 수 있게 되었다. 이는 기존 구현을 깨지 않고 인터페이스에 새로운 멤버를 추가할 수 있게 한다.
-
정적 멤버: 인터페이스 내에 static 메소드와 필드를 정의할 수 있게 되었다.
-
접근 지정자: 멤버에 public 외의 접근 지정자를 사용할 수 있게 되었다.