Java

[Java] extends 와 implements 의 차이

hyunki.Dev 2023. 1. 10. 23:54

자바에 있어서 OOP, 상속과 관련되 개념은 매우 중요하다고 할 수 있습니다. 

 

자바 코딩의 핵심이라고 볼 수 있으며 자바 관련 조금만 큰 규모 혹은 작은 규모더라도 SpringBoot 코딩을 하다보면 반드시 사용하게 되는  개념 입니다.

 

얼마 전 회사에서 하나의 시스템과 다른 시스템을 연동하는 20여개의 api 를 개발할 때도 implements를 이용했습니다. 이 때HttpClient.java 라는 파일에는 public ResponseDto getInformation();  과 같은 형식으로 개발할 api 들에 대해 나열한 interface를만들고 HttpClientImpl 이라는 구현체를 만들어 구현체에서 각 api 들을 구현했습니다. 이렇게 코딩을 하게 되면 api 의 스펙이 도중에 변경 되더라도 HttpClientImpl 구현체만 수정을 하면 되고 해당 api를 사용할 때에는 HttpClient에 접근하여 각 메소드를 실행하면 되기 때문에 비즈니스 요구사항의 변경에 따른 리팩토링이 용이합니다.

 

이 때 문득 든 생각이 아무렇지 않게 public class HttpClientImpl implements HttpClient 와 같은 형식으로 개발하여 extends와의 차이는 무엇이지? 하는 생각이 들어 이 포스팅을 작성하게 되었습니다.

 

 

상속(Inheritance)

자바의 상속에 대한 개념을 설명할 때 가장 많은 예를 드는 것이 생물에 관한 예시입니다.

 

생물 --> 동물, 식물  로 나누어지며

 

동물은 다시  동물 --> 포유류, 파충류, 조류  로 나누어집니다.

 

이와 같은 구조를 가졌을 때 

  • 단어 하나하나는 모두 객체 (Object)이고, 자바 용어로는 class입니다. 동물클래스, 포유류 클래스... 
  • 이러한 계층을 표현하기 위해 만들어진 것이 바로 상속입니다.
  • 하위 객체는 상위 객체 클래스(부모)의 특징을 물려받습니다.

 

예를 들어 동물이 '잠을 잔다' 라는 특징을 갖고 있으면 포유류, 파충류, 조류 모두 '잠을 잔다'라는 특징을 갖게 됩니다.

즉 sleep() 이라는 메소드를 포유류, 파충류, 조류 클래스 모두 사용할 수 있다는 뜻입니다.

 

또 다른 예로 나이(age) 라는 변수를 갖고 있다면 이 역시 모든 동물을 상속받은 클래스에서 물렵다게 됩니다. 

 

이러한 메소드 또는 변수를 직접 구현하는가 아니면 그대로 사용하는가에 따라서 상속의 형태가 달라지게 됩니다.

 

1. extends 

  • 부모에서 선언과 메소드 정의를 모두하며 자식은 이를 사용할 수 있습니다.


2. implements

  • 부모 객체는 선언만 하게 되며 이에 대한 내용은 자식 객체에서 오버라이딩(재정의) 하여 사용해야 합니다. 


3. abstract  

  • extends 와 interface 의 혼합으로 extends 하되 일부는 추상 메소드로 구현하게 되어 있습니다. 

 

extends(상속)

- 부모의 메소드를 그대로 사용할 수 있으며 오버라이딩 할 필요 없이 부모 클래스에 구현되어 있는 것을 그대로 사용 할 수 있습니다.

 

class Vehicle {
  protected int speed = 4;
  
  public int getSpeed(){
    return speed;
  }
  public void setSpeed(int speed){
    this.speed = speed;
  }
}

class Car extends Vehicle{
  public void printspd(){
    System.out.println(speed);
  }
}

public class ExtendsSample {
  public static main (String[] args){
    Car A = new Car();
    System.out.println(A.getSpeed()); //부모 클래스의 getSpeed() 메서드 사용가능
    A.printspd();
  }
}

 

Car 라는 클래스가 Vehicle 탈 것 클래스를 상속받았으며 getSpeed() 메소드로 speed를 print 가져왔습니다. speed를 직접 사용한 것은 extends를 했으니 메소드 뿐만 아니라 변수까지 사용 가능해 진 것입니다.

 

참고로 접근제어자는

public : all

protected : 상속 또는 동일 패키지

default : 상속 && 동일패키지

private : 클래스 내부

 

입니다. 

 

그리고 참고적으로 자바에서는 부모 클래스가 여러개인 다중상속은 지원하지 않습니다.

 

이를 대신하여 나온 것이 implements 인터페이스 상속입니다.

 

Implements(상속)

interface TestInterface{
  public static int num = 8;
  public void fun1();
  public void fun2();
}

class InterfaceExam implements TestInterface{
  @Override
  public void fun1(){
    System.out.println(num);
  }
  
  @Override
  public void fun2() {
    
  }
}

public class InterfaceSample{
  public static void main(String args[]){
    InterfaceExam exam = new InterfaceExam();
    exam.fun1();
  }
}

 

위의 implements 와 같은 방식이 이번에 실제로 회사에서 Http 통신을 하는 Client를 개발할 때 사용했던 방식입니다.

 

implements의 가장 큰 특징은 부모의 메서드를 반드시 재정의 Override 해야 한다는 것입니다.

또한 이, implements는 다중 상속이 가능합니다. 

 

public class A implents C, D...  이 가능합니다.

 

그리고 상속해주는 class는 interface 여야 합니다.

 

 

  • extends는 일반 클래스와 abstract 클래스 상속에 사용되고, implement는 interface 상속에 사용됩니다.
  • class가 class를 상속받을 땐 extends를 사용하고, interface가 interface를 상속 받을 땐 extends를 사용합니다.
  • class가 interface를 사용할 땐 implements를 써야하고
  • interface가 class를 사용할 땐 implements를 쓸수 없습니다.
  • extends는 extends는 클래스 한 개만 상속 받을 수 있고 자신 클래스는 부모 클래스의 기능을 사용합니다.
  • implements는 여러개 다중으로 사용 가능하며 설계 목적으로 구현이 가능합니다.
  • implements한 클래스는 implements의 메서드를 전부 재정의하여 사용해야 합니다. --> 사용하지 않으면 IDE(Intellij)에서 빨간줄로 오류가 표시되며 '옵션 + Enter' 키를 사용하면 Overriding 해야 하는 메서드를 자동으로 생성해줍니다.