자바에 있어서 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 해야 하는 메서드를 자동으로 생성해줍니다.
'Java' 카테고리의 다른 글
Java 에서의 예외처리 (0) | 2023.06.03 |
---|---|
[Mockito & JUnit] @Mock 과 @InjectMock (0) | 2023.03.28 |
[Java] 접근 제한자란 무엇인가 (0) | 2023.03.08 |
자바의 자료구조 - 컬렉션 프레임워크(Collection Framework) (0) | 2023.02.05 |
[Java] AtomicInteger 사용하기 (0) | 2023.01.07 |