추상 클래스와 인터페이스의 차이

들어가기

추상 클래스와 인터페이스 차이점은 관심 있게 생각해보지 않는다면 그냥 넘어갈 가능성이 높다. 그러나 한 번만이라도 그 차이를 명확하게 짚고 넘어가면 이후에는 혼동을 할 필요가 없어지는 한번은 짚고 넘어가는 것이 좋다.

추상 클래스란 무엇인가?
공통된 상태와 동작을 제공하면서, 일부 동작은 하위 클래스에 구현을 강제할 때 사용

인터페이스란 무엇인가?
다양한 타입에 공통된 규약(기능)을 강제하여 일관된 사용을 가능하게 할 때 사용

추상 클래스

추상 클래스는 클래스가 할 수 있는 것은 거의 할 수 있다. 단, 추상 클래스 자체를 객체화 시키는 것은 불가능하다. 이를 해결하기 위해서는 상속을 하여 하위 클래스를 통해 해결할 수 있다.

 

또 다른 특징들은 다음과 같이 있다.


추상 클래스의 특징

인스턴스화(객체화) 불가능 추상 클래스는 직접 객체 생성 불가능, 상속 받은 하위 클래스에서만 가능함
추상 메서드 포함 추상 메서드란, 상속 받는 하위 클래스가 구체적인 구현을 하도록 메서드를 선언만 한것
일부 구현 포함 가능 기본 상속과 같이 구체적인 메서드를 구현해도 상속받은 하위 클래스는 상위 클래스의 메서드를 사용 가능

 

추상 클래스에서는 추상 메서드를 포함시킬 수 있는데, 이는 본문이 없이 함수만 선언해준 것이다. 본문이 없으니 구현이 없다. 그래서 추상 클래스를 상속받은 하위 클래스들은 추상 메서드가 있다면 이를 강제로 구현해야하는 강제성이 발생한다.

 

물론 추상 클래스가 무조건 추상메서드만 사용해야 하는 것은 아니다. 일반 클래스처럼 상속해서 사용될 수 있는 함수들을 구현해놓을 수도 있다.


추상 클래스의 예시

추상 클래스의 기본적인 형태는 다음과 같다.

public abstract class Player
{
		public string nickname;
		
		public void Move()
		{
				//일반적인 메서드
				//이 중괄호에 기능 구현
		}
		public abstract void Jump(); //추상 메서드
}

 

추상이라는 뜻을 가지고 있는 abstract가 클래스 앞에 붙어 있는 것을 확인 할 수 있다.

이는 추상 메서드에도 똑같이 붙어서 이 함수가 추상 메서드임을 밝힌다.


추상 클래스의 사용

1. 코드 재사용성
2. 구체적인 기본 동작 제공
3. 공통된 계약 강제

 

크게 세가지의 이유가 존재한다. 1번과 2번의 경우는 우리가 클래스의 상속을 통해 얻을 수 있는 일반적인 이유 또는 기대하는 효과이지만, 3번의 경우는 추상 클래스만이 가지는 알파이자 오메가인 가장 대표적인 이유이다.

공통된 계약을 강제하면서도, 각 하위 클래스들의 구체적인 동작을 독립적으로 구현이 가능하기 때문이다.

 

조금 더 구체적으로 넘어가서 언제 추상 클래스의 사용을 고려해야 하는가에 대해서도 세가지를 얘기 할 수 있다.

 

  1. 공통된 기능은 있지만, 구체적인 구현을 달라야 할 때
  2. 계층 구조에서 일부 기능은 미리 제공하고, 일부는 자식 클래스에 맡길 때
  3. 일관된 인터페이스를 제공하면서도 다양한 구현을 허용하고자 할 때

예를 들어 개구리동물이다. 이때, 동물은 식물 무생물 같은 하나의 개념이며, 이는 추상 클래스에 해당한다.

동물은 움직이고 먹는다. 하지만, 개구리와 새의 이동 방식은 명확하게 차이가 난다. 이는 추상 메서드에 해당한다.

 


인터페이스

클래스들은 서로 상속을 하는 물려받는다는 느낌이 느껴지는 반면, 인터페이스는 장착의 개념에 더 가깝다. 또한 클래스에 비해 비교적 필요성을 못느끼는 경우가 많아서 인터페이스에 대해 가볍게 생각하는 경우가 있다.

 

그런 인터페이스의 특징은 다음과 같다.


인터페이스의 특징

1. 구현 부분이 없다.
2. 이벤트, 인덱서, 메서드 또는 속성의 선언만 포함한다.
3. 인터페이스끼리만 상속이 이루어진다.

 

인터페이스의 특징은 많이 없다. 구현 부분이 없는 것은 추상 메서드와 닮았으며, 강제성이 존재한다는 것 역시 같다. 해당 인터페이스를 상속(장착)한 객체는 구현을 강제당한다.

 

인터페이스의 예시

interface IMyInterface
{
    void MyMethod();
    int MyProperty { get; set; }
}

 

인터페이스는 이름에 "I"를 붙여서 자신이 인터페이스임을 밝힌다.

 

class MyClass : IMyInterface
{
    public void MyMethod()
    {
        // Implementation details here
    }

    public int MyProperty { get; set; }
}

 

클래스가 인터페이스를 장착하면 인터페이스에 정의된 모든 메서드와 속성에 대한 구현을 제공해야 한다. (강제성)

 

interface IMyBaseInterface
{
    void MyBaseMethod();
}

interface IMyDerivedInterface : IMyBaseInterface
{
    void MyDerivedMethod();
}

 

인터페이스끼리만 상속이 가능하다.

 


인터페이스의 사용

1. 객체끼리 느슨한 결합을 원할 때
2. 다양한 타입에 동일한 기능을 보장하고 싶을 때
3. 다중 상속이 필요할 때
4. 역할을 부여하고 싶을 때

 

우리는 동일한 기능을 상속을 통해서만 구현을 해왔다면, 인터페이스는 그동안 해왔던 모든 규칙을 깨부수는 느낌이다. 장착의 개념으로 더 강한 인터페이스는 다양한 타입에 적용이 가능하다.

 

예를 들면 비행기탈것(상위 클래스)이고, 동물(상위 클래스)이지만, 둘 다 나는 행동이 가능하다.

 

이를 코드로 구현한다면, 상위 클래스가 아예 다른 두 객체가 동일한 기능을 공유할 수 있다는 뜻이다.

(IFlyable 같은 인터페이스 만들어서 구현할 수 있음)

 

또한, 인터페이스는 상속처럼 하나만 장착되지 않고 여러개를 한 곳에 장착시키는 것이 가능하다.

 


마무리

추상 클래스와 인터페이스를 공부하다가 많이 애매모호한 부분이 많고 이전 포스팅에도 나도 몰라서 얼렁뚱땅 넘겨버린 부분들이 보여서 역순으로 다시 타고 들어가며 공부를 하고 있는 중이다. 다음은 아마, 다형성과 캡슐화에 대해서 글을 쓸 것 같다.

 

추상 클래스와 인터페이스의 차이점을 한번 더 정리하고 마무리하도록 하겠다.

비교 추상클래스 인터페이스
인스턴스화 불가능 (상속을 통해서 가능) 불가능 (장착을 통해서 가능)
구현 포함 여부 구체적인 메서드 구현 포함 가능 불가능(C# 8.0 이후 기본 메서드 구현 가능)
상속 가능 여부 하나만 상속 가능 여러 인터페이스 구현 가능
사용 목적 공통된 기본 기능과 추상 메서드 제공 클래스가 따라야할 일관된 계약 정의
접근 제한자 원하는 대로 수정 가능 기본적으로 public이며 수정 불가
생성자와 소멸자 포함함 포함하지 않음