오히려 좋아..

상황이 나쁘게만 흘러가는 것 같을 때 외쳐보자.. .

궁금한 마음으로 포트폴리오 보기

Paradigm/OOP

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

junha6316 2022. 8. 21. 17:00

매번 사용하면서도 모르는 추상클래스와 인터페이스의 차이에 대해 설명하려고 한다.

 

구글에 검색해봐도 사실 어려운 이야기만 잔뜩 있어서 이게 뭐지 라는 생각만 든다.

나는 이 둘의 차이를 용도의 차이 측면에서 보려고 한다. 

결론부터 말하면 추상클래스는 확장해서 사용하기 위함이고 인터페이스는 설계를 위함이다. 아직 무슨 말인지 감이 오지 않을 것이다. 

먼저 추상 클래스의 예시를 보자!

 

1. 추상 클래스 

 예를 들어 Company 라는 추상 클래스가 있고 이 클래스는 아래와 같다. 추상클래스는 자식 클래스들의 공통된 구현을 추상 클래스 내에 정의된 상수나 구현을 이용해 중복을 없애고 추상 메서드를 이용해 자식들의 구현을 강제한다.

abstract class Company {
  private name: string;
  private employees: Employee[];

  public getName() {
    return this.name;
  }
   
   /**
    * 돈 만들기
    * @param money 
    */
   abstract moneyMaking(money: Money): Money;
    
/**
* 사원들 갈기
* @returns 
*/ 
  protected squeezeEmployes() {
    const results = this.employees
      .filter((employee) => employee.status == "healty")
      .map((employee) => {
        employee.status = "tired";
        return employee;
      }).length;
    return results;
  }
}

 

 Company는 기본적으로 돈을 벌어야하지만 각각 회사마다 돈버는 방법은 다르기 때문에 추상클래스로 두었다. 하지만 `직원들 갈기` 는 모든 회사가 할 수 있으므로 구현한 채 추상클래스에 두었다. 추상클래스를 상속받는 자식 클래스들인 삼성, SK, 중소기업1은 자기들 만의 돈버는 방법이 있기 떄문에 moneyMake은 각자 구현하고 moneyMake의 내부 로직으로 직원들 갈기를 사용할 것이다. 만약 추상 클래스가 없었다면 모든 Company 처럼 사용되는 클래스에 `직원들 갈기`를 구현해줘야 했을 것이다. 하지만 추상 클래스를 통해 공통된 구현은 묶어 코드 중복을 줄이고 상황마다 달라지는 구현은 abstract로 두어 자식 클래스에게 해당 메서드를 구현을 맡기는 것이다.

 

정리하자면 추상클래스는 기능의 확장을 위한 클래스이다. 자식 클래스들의 공통된 기능은 묶고 자식마다 달라지는 구현을 abstract로 두어 코드의 중복을 줄이고 유연한 설계를 가능하게 한다.

 

 2. 인터페이스

추상 클래스가 자식 클래스을 통한 기능의 확장이 목적이라면 인터페이스는 설계를 위함이다. 가령 위의 예시에서 어떤 회사는 3년 근속시 안식 휴가를 보내주는 회사도 있고 그렇지 않은 회사들도 있다. 예를들어 회사A, B는 안식휴가를 보내주는데 C는 안보내준다고 가정해보자!그렇다면 회사 A, B에 특정 메서드를 선언해줘야하는데 동일한 메서드 이름을 갖고 있어야 한다. 물론 2개 일 때는 이름을 통일시키기 쉽지만 상속받는 클래스가 10개라면 20개라면 과연 아무런 장치없이 메서드 이름 관리가 될까? 그리고 어떤 클래스가 안식휴가를 보내주는지 알기 위해 일일히 함수의 구현부를 찾아가 해당 메서드가 있는지 검색하는 것도 쉬운 일이 아니다. 이럴 때 나즈막히 외쳐보자. "interface가 필요하다" 맞다 이럴때 인터페이스가 필요하다. 아래처럼 구현 할 수 있다. 

// 안식휴가 영어단어는 sabbatical이지만 너무 어려운 단어인거 같아 RestVacation이라 했다.
interface RestVacationable {
  heyGoToVacation: () => {};
}

 

이제 이 부분을 CompanyA에서 구현해보자

class CompanyA extends Company implements RestVacationable {
  public moneyMaking() {
    return 1000;
  }

  public heyGoToVacation() {
    console.log("휴가 다녀와");
    return {};
  }
}

 

이제 class 정의 부분에서 어떤회사가 안식 휴가를 보내주는지 알게 되었고 안식 휴가를 보내는 메서드의 인터페이스도 관리 할 수 있게 되었다.

 

3. A is ~ , A has  ~ function

위의 예에서 아래와 같은 이론을 도출 할 수 있다.

A is 관계에서는 추상 클래스를 사용하고 A has 관계에서는 인터페이스를 사용한다.

가령 Samsung is Company 관계이기 때문에 Company를 추상클래스로 구현하는 거고 A has  RestVacationable function 이기 때문에 인터페이스로 구현하는 것이다. 

 

4. 정리

추상클래스의 목적은 상속을 통해 코드의 중복을 없애면서 자식 클래스를 두어 유연성을 얻기 위함이고 인터페이스의 목적은 설계를 일괄적으로 관리하기 위함이다.

 

'Paradigm > OOP' 카테고리의 다른 글

클래스와 객체  (0) 2021.09.29
추상화  (0) 2021.09.28
의존성  (0) 2021.09.28
역할, 책임, 협력, 메세지  (0) 2021.09.28
추상화 매커니즘  (0) 2021.09.28