Abstract class VS Interface 차이

Onam Kwon·2023년 2월 22일
0

CS

목록 보기
20/22

C++ 가상함수, 순수가상함수

  • Pure virtual function(순수 가상함수, 추상메소드): 파생 클래스에서 반드시 재정의해야 하는 함수를 말합니다.
    • 일반적으로 함수의 동작을 정의하는 본체를 가지고 있지 않으며 따라서, 파생 클래스에서 재정의하지 않으면 사용할 수도 없습니다.
    • 이는 Java의 abstract 메소드와 동일합니다.
  • virtual funciton(가상함수): 파생 클래스에서 재정의할 것으로 기대되는 함수입니다.
    • 확실히 알아야 할 점은, 반드시 재정의해야 하는 함수가 아니라 재정의가 가능한 함수를 말합니다.
class MyBaseClass {
public:
    // pure virtual function
    virtual void doSomething() = 0;
    
    // virtual function
    virtual void doSomethingElse() {
        // implementation goes here
    }
};

Abstract class (추상 클래스)

  • Abstract class(추상 클래스)란 하나 이상의 순수 가상 함수를 포함하는 클래스를 추상클래스라고 하며, 이 클래스로부터 파생된 모든 클래스에서는 이 가상 함수를 반드시 재정의해야 한다.
  • 따라서 abstract class(추상클래스)는 객체화 할 수 없다.
    • 동작이 정의되지 않은 순수 가상 함수를 가지고 있기 때문.
    • 상속을 통해 파생 클래스를 만든 후, 파생 클래스에서 순수 가상 함수를 모두 오버라이딩 한 후에 해당 클래스에서 인스턴스를 생성할 수 있다.
  • 또한 추상클래스는 상태나 구현을 포함할 수 있다.
    • 일반 변수나 일반 함수를 가질 수 있다. 하지만 하나 이상의 추상메소드를 포함해야 한다.
  • 추상클래스의 목적은 파생클래스가 그 기능을 상속받아 이용하고 확장시키는데 있다.
  • 추상 클래스는 단일 상속만 가능하다.

Interface (인터페이스)

  • C++에서 인터페이스는 사실 공식적으로 지원하지 않아 간접적으로 구현하는 방법을 사용하며 따라서 인터페이스로 사용한다는 것을 알리기 위해 인터페이스의 이름은 항상 I로 시작하도록 약속되어있다.
    • xxxable로 이름을 하는 경우도 있는데 이건 Java에서만 그런지 모두 그런지는 모르겠다.
  • 인터페이스란 모든 메소드가 추상 메소드(pure virtual function)인 경우를 말합니다.
    • 따라서 인터페이스 클래스에는 구현부가 존재하지 않는다.
  • interface 역시 인스턴스를 생성할 수 없다(객체화 할 수 없다).
    • 동작이 정의되지 않은 추상 메소드를 포함하고 있기 때문.
    • abstract class 와 마찬가지로 파생 클래스에서 인스턴스 생성 가능.
  • interface 는 상태나 구현을 포함할 수 없다.
    • 일반 변수나 일반 함수를 가질 수 없다.
  • interface 는 상속받은 구현 객체가 같은 동작을 하는것을 목적으로 한다(같은 이름의 메소드를 사용하는것을 목적으로 한다).
  • 인터페이스는 다중 상속이 가능하다.
#include <iostream>
using namespace std;

class Camera {
public:
	void take() {
    	cout<<"Take a picture with a camera."<<endl;
    }
}

class Person {
public: 
	void useCamera(Camera* p) {
    	p->take();
    }
}
  • 하지만 여기서 더 좋은 카메라가 나타난다면 우리는 기존에 존재하던 Camera클래스를 수정해야한다.
    • 이는 SOLID의 open close principle(개방 폐쇄의 법칙)에 위배된다.
      • 기능확장(모듈, 클래스, 함수 추가)에 열려있고 기존 코드 수정에는 닫혀있음.
    • 따라서 더 괜찮은 카메라가 나타나도 기존의 코드를 수정하는 일이 일어나선 안된다.
  • 아래와 같이 인터페이스를 장착하면 위의 문제점을 해결할 수 있다.
#include <iostream>

using namespace std;

// There is a promise that people decided to refer an interface starting with letter 'I'. 
// Thus, notice below "ICamera" is an interface.  
struct ICamera 
{
    virtual void take() = 0;
};

class People
{
public:    
    void useCamera(ICamera* p) { p->take();}
};

class Camera : public ICamera
{
public:
    void take() 
    {
         cout<<"Take a picture."<<endl; 
    }
};

class BetterCamera : public ICamera
{
public:
    void take() 
    {
         cout<<"Take a better picture."<<endl; 
    }
};

int main()
{
    People p;
    Camera c1;
    p.useCamera(&c1);
    
    BetterCamera bc;
    p.useCamera(&bc);

    return 0;

}
  • 위처럼 인터페이스를 통해 얻을수 있는 장점은 People의 인스턴스인 pICameratake 함수를 사용해 어떤 카메라를 사용하든 주입받는 카메라를 같은 함수로 사용할 수 있다.
    • ICamera 인터페이스 덕분!
  • 나중에 BetterCamera 보다 더 좋은 BestCamera가 나타난다 하더라도 p는 같은 메소드인 take를 사용하면 인터페이스를 통해 BestCamera의 카메라를 사용할 수 있다.
  • 인터페이스의 목적은 함수의 껍데기만 있으며 해당 함수의 구현을 파생 클래스에서 강제로 수행하도록 하기 위함이다.

abstract VS interface 차이점 및 공통점

  • 추상클래스와 인터페이스는 사실 비슷하면서도 다른부분이 존재한다.

차이점

abstractinterface
변수 사용 여부사용 가능사용 불가능
메소드 사용 가능 여부일반 메소드 포함 가능추상 메소드만 포함 가능
다중상속 가능 여부불가능(단일상속)가능
클래스 구성 요소일반변수+일반메소드+추상메소드(하나 이상 필수)오직 추상 메소드만 가능

공통점

  • 추상 메소드를 포함하고 있다.
  • 인스턴스를 생성할 수 없다(객체화 할 수 없다).
    • new 생성자를 사용할 수 없다.
  • 따라서 추상클래스나 인터페이스를 물려받은 클래스의 인스턴스를 사용해야한다.
  • 추상 메소드를 반드시 구현해야한다.
    • 안하면 컴파일에러 발생.

목적

  • 추상클래스는 하위 클래스들의 공통점들이 모여 추상화되어 만들어진 클래스이다.
    • 좀 더 상위 카테고리 개념.
  • 추상클래스는 클래스간의 논리적 연관 관계를 생성하는 것에 목적이 크다.
  • 추상클래스는 자신의 기능들을 하위 클래스로 확장시키는 개념.
  • 추상클래스는 클래스간 명확한 계층 또는 논리적 관계를 나타낼때 추상클래스를 사용한다.
    • 논리적 관계의 몇가지 예시는 아래와 같다.
    • 원, 삼각형, 사각형 -> 상위 카테고리인 도형 클래스.
    • 강아지, 고양이, 앵무새 -> 상위 카테고리인 동물 클래스.
    • 에어팟, 맥북, 아이폰 -> 상위 카테고리인 애플 클래스.
  • 인터페이스는 부모 자식 관계의 논리적인 관계보단, 공통 기능이 필요할 때 탈부착 가능한 개념으로 추상 메소드를 구현하며 상위 클래스인 인터페이스를 생성한다.
  • 인터페이스에 명시된 메소드를 파생클래스에서 따로 구현해 각 클래스의 목적에 맞게 사용하는 개념.
  • 인터페이스는 서로 관련성이 없는(논리적 관계가 형성되어 있지 않은) 클래스를 추상화 할때 사용할 수 있다.
    • 예를들어, 여러 종류의 동물들이 있을 때, 동물들이 구현해야 하는 공통된 기능들을 인터페이스로 정의할 수 있습니다. 이 때 인터페이스에는 동물이 가지고 있어야 할 공통된 기능(메소드)을 추상 메소드(순수 가상 함수)로 정의하고 파생클래스에서 해당 메소드를 구현합니다. 이렇게 인터페이스를 사용하면 다른 클래스들 간의 논리적인 관계가 형성되어 있지 않아도 공통된 동작을 지원할 수 있습니다.
  • 인터페이스는 다중상속이 필요할 때 사용할 수 있습니다.
profile
권오남 / Onam Kwon

0개의 댓글