Interface
Interface는 클래스나 구조체가 구현해야 하는 메서드, 속성, 이벤트 및 인덱서를 정의할 수 있는 계약(contract)을 의미한다. 인터페이스는 이를 구현하는 클래스나 구조체가 반드시 포함해야 하는 멤버들의 목록을 명시하지만, 실제 구현은 제공하지 않는다.
인터페이스는 다음과 같은 특성을 가진다.
인터페이스는 특정 기능을 제공하기 위한 계약을 정의한다.
인터페스를 상속한 클래스나 구조체에서는 인터페이스에 정의된 모든 멤버와 메소드를 강제 구현해야 한다.
C#에서 클래스는 다중 상속을 지원하지 않지만, 인터페이스는 다중 상속이 가능하다.
Interface 정의
1
2
3
4
5
public interface IAnimal
{
void Speak();
void Eat();
}
Interface 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Dog : IAnimal
{
public void Speak()
{
Console.WriteLine("Bark");
}
public void Eat()
{
Console.WriteLine("Dog is eating.");
}
}
public class Cat : IAnimal
{
public void Speak()
{
Console.WriteLine("Meow");
}
public void Eat()
{
Console.WriteLine("Cat is eating.");
}
}
Interface 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Program
{
static void Main()
{
IAnimal dog = new Dog();
IAnimal cat = new Cat();
dog.Speak(); // 출력: Bark
dog.Eat(); // 출력: Dog is eating.
cat.Speak(); // 출력: Meow
cat.Eat(); // 출력: Cat is eating.
}
}
Interface VS Class VS Abstract Class
인터페이스와 클래스는 모두 상속이 가능하다. 하지만 인터페이스는 다중 상속이 가능하고, 클래스는 단일 상속만 가능하다. 그리고 둘은 상속을 하는 사용 목적에서 확실하게 구분이 되어진다.
인터페이스의 사용목적은 특정 기능을 여러 클래스에 걸쳐 강제하기 위해 사용한다.
클래스는 객체를 생성하고, 데이터와 메서드를 포함하여 실제 동작을 구현하는 데 사용한다.
추상 클래스는 공통된 기본 구현을 제공하고, 서브클래스가 이를 확장하고 구체적인 동작을 정의하도록 강제한다.
| 구분 | 인터페이스 (Interface) | 클래스 (Class) | 추상 클래스 (Abstract Class) |
|---|---|---|---|
| 정의 | 계약(Contract) | 객체의 설계도 | 부분적으로 구현된 클래스 |
| 멤버 구현 | 구현 불가 | 구현 가능 | 부분적으로 구현 가능 |
| 인스턴스 생성 | 불가 | 가능 | 불가 |
| 다중 상속 | 가능 | 불가 | 불가 |
| 접근 제한자 | 없음 (모든 멤버는 암묵적으로 public) | 모든 접근 제한자 가능 | 모든 접근 제한자 가능 |
| 생성자 | 없음 | 있음 | 있음 (하지만 직접 인스턴스화는 불가) |
| 사용 사례 | 다중 상속이 필요하거나 특정 계약을 강제할 때 | 일반적인 객체 지향 프로그래밍 | 기본 구현을 제공하고 서브클래스가 확장할 때 |
| 필드 | 불가 | 가능 | 가능 |
| 속성 | 선언만 가능 | 가능 | 가능 |
| 메서드 | 선언만 가능 | 가능 | 선언 및 일부 구현 가능 |
좀 더 편하게 생각하자면 인터페이스는 여러 클래스에서 공통으로 사용하기로 한 약속이다. 따라서 그 약속의 이행은 인터페이스를 상속받은 클래스에서 구현을 통해서 이행하게 된다.
예를 들면 동물이라는 인터페이스에 짖다라는 메소드가 있을 때, 이 인터페이스를 상속받은 강아지라는 클래스와 고양이라는 클래스가 짖다를 구현할 때 같은 소리가 나지 않는다. 다른 소리로 짖다를 구현하면서 약속을 이행하게 된다.
추상 클래스는 확장이라는 용도로 사용한다. 뭔가 확실히라게 구현하기 애매한 부분들을 확장해서 사용하기 위해 선언만 해놓고 필요할 때 추상 클래스를 상속받은 자식 클래스에서 구현을 해서 알아서 쓴다