일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 자바
- 비관적 락
- 데이터베이스
- 페이지네이션
- JPA
- 자료구조
- Kotlin
- 정규화
- 스레드 풀
- buildSrc
- Dirty Checking
- Kafka
- DB
- 캐시 오염
- 3-way handshaking
- MSA
- null
- Spring
- java
- HTTP
- ocp
- 삽입 이상
- 네트워크
- Redis
- 갱신 이상
- AWS
- 삭제 이상
- gatway
- well-know port
- 낙관적 락
- Today
- Total
어 나 갱수.
[Java] 추상클래스 VS 인터페이스 🤨 본문
오늘은 자바에서 사용되는 추상클래스와 인터페이스에 대해 알아보겠습니다!
추상클래스란?
우리가 지금까지 사용하던 클래스는 구체적으로 데이터를 담아 인스턴스화하여 직접 다루는 클래스입니다.
그 반대로 구체적이지 않은 추상적인 데이터를 담고 있는 클래스를 '추상 클래스'라고 부릅니다.
그래서 추상 클래스는 일반 클래스와 다르게 자체적으로 인스턴스화를 시키지 못합니다. 자체적으로 객체를 생성할 수 없습니다.
상속을 통해 자식 클래스에서 인스턴스를 생성할 수 있습니다.
자바에서는 abstact 키워드를 사용해서 이 클래스가 추상 클래스라고 표현합니다.
추상 클래스에는 추상 메서드가 있는데 추상 메서드는 메서드의 선언부만 있고, 구현부는 아직 미완성인 채로 남겨둔 메서드입니다.
부모 클래스에서 추상 메서드를 작성해 놓고 추상 클래스를 상속받는 자식 클래스에서 해당 추상 메서드에 대한 구현부를 작성합니다.
abstract class Transportation {
// 추상 메서드
public abstract void go();
}
class Car extends Transportation {
// 상속받은 추상 메서드를 구현
public void go() {
System.out.println("Car go");
}
}
추상 클래스를 상속받은 클래스는 추상 클래스가 가지고 있는 추상 메서드를 반드시 오버라이딩 해야 합니다.
만약 상속받은 클래스에서 메서드를 모두 오버라이딩 하지 않는다면 상속받은 클래스도 추상 클래스가 된다.
abstract class Transportation {
// 추상 메서드
public abstract void go();
public abstract void stop();
}
class Car extends Transportation {
// 상속받은 추상 메서드를 구현
public void go() {
System.out.println("Car go");
}
// Transportation의 추상 메서드를 모두 오버라이딩하지 않으면
// Car 클래스도 추상 클래스가 된다.
}
추상 클래스 사용이유
객체들의 필드와 메서드의 이름을 통일하여 소스의 가독성을 높이기 위해서입니다. 변수와 메서드의 네이밍은 소스 가독성에 큰 영향을 줍니다. 예를 들어 동물이라는 추상 클래스에 "짖다"라는 메서드명이 각자 다르다고 생각해 봅시다. 개 클래스에서는 "Bark()", 사자 클래스에는 "Roar()", 그리고 늑대 클래스에서는 "Howl()"이라는 메서드명으로 각각 지정하였을 때, 딱 봤을 때는 좋은 네이밍 같지만 동일하게 짖다는 기능의 메서드를 다른 네이밍으로 하는 것을 보면 소스의 가독성이 떨어집니다. 그래서 소스의 가독성을 키우려면 동물이라는 추상 클래스에 "Bark()"라는 메서드를 만들고 그 추상 클래스의 Bark() 함수를 자식 클래스에서 상속받아 네이밍을 통일하는 것이 좋습니다.
인터페이스란?
추상클래스가 미완성 설계도라면 인터페이스는 기본 설계도라고 할 수 있습니다. 인터페이스도 추상클래스처럼 다른 클래스를 작성하는데 도움을 주는 목적으로 작성하고 클래스와 다르게 다중상속이 가능합니다.
특징
- 인터페이스도 필드를 선언할 수 있지만 변수가 아닌 상수(final)로서만 정의할 수 있다.
- 인터페이스는 객체가 아니므로 생성자를 사용할 수 없습니다.
- 자식클래스는 부모 인터페이스의 추상 메서드를 모두 오버라이딩해야 합니다.
상수와 메서드
- 모든 변수는 상수로 선언됨 public static final
- final, static이 자동으로 추가
- 모든 메서드는 추상 메서드로 선언된 public abstract
- 추상 메서드만 가짐
- abstract를 생략해도 자동으로 추가
interface 인터페이스이름{
public static final 타입 상수이름 = 값;
public abstract 타입 메서드이름(매개변수목록);
}
// --------------------------------------------------------
interface TV {
int MAX_VOLUME = 10; // public static final 생략 가능
int MIN_VOLUME = 10;
void turnOn(); // public abstract 생략 가능
void turnOff();
void changeVolume(int volume);
void changeChannel(int channel);
}
인터페이스 구현
- 인터페이스도 추상 클래스처럼 그 자체로는 인스턴스를 생성할 수 없으며, 추상 클래스가 상속을 통해 완성되는 것처럼 인터페이스도 구현부를 만들어주는 클래스(객체)에 상속을 받아야 합니다.
- 클래스에 인터페이스를 구현하고 싶다면, implements 키워드를 쓴 후에 인터페이스를 나열하면 된다.
- 인터페이스의 가장 큰 장점은 여러 개를 다중 구현(다중 상속)이 가능하다는 것입니다.
- 자식 클래스에 상속(extends)과 인터페이스 구현(implements)이 동시에 가능합니다.
인터페이스 자체 상속
- 클래스끼리 상속을 통해 확장을 하듯이, 인터페이스 자체를 확장시키고 싶다면 extends를 통해 인터페이스를 상속시킬 수 있다.
- 클래스와 마찬가지로 자식 인터페이스는 부모 인터페이스에 정의된 멤버를 모두 상속받는다.
- 클래스끼리는 다중 상속이 불가능하지만, 인터페이스는 다중 상속이 가능하다.
interface Changeable{
/* 채널을 바꾸는 기능의 메서드 */
void change();
}
interface Powerable{
/* 전원을 껐다 켰다 하는 메서드 */
void power(boolean b);
}
// 채널 기능과 전원 기능을 가진 인터페이스들을 하나의 인터페이스로 통합 상속
interface Controlable extends Changeable, Powerable {
// 인터페이스끼리 다중 상속하면 그대로 추상 멤버들을 물려 받음
}
인터페이스 사용하는 이유
- 인터페이스는 코드와 인터페이스로 생성된 객체(구현 클래스)를 중간에서 중계해 주는 역할을 합니다.
- 개발 코드에서 인터페이스의 메서드를 호출하면, 인터페이스는 객체의 메서드를 호출하는 방식입니다.
- 인터페이스에서 정의된 객체(구현 클래스)는 인터페이스와 동일한 메서드 이름, 매개 타입, 리턴 타입을 가진 메서드를 가지고 있어야 합니다.
- 이러한 과정을 통해 클래스 간의 결합도를 낮춘 더 좋은 프로그래밍을 할 수 있습니다.
추상 클래스 VS 인터페이스
추상클래스와 인터페이스의 공통점은 추상메서드를 사용할 수 있다는 것입니다. 그럼 왜 두 가지로 나눠서 사용할까요?
두 개를 나누는 가장 큰 이유는 사용용도가 다르기 때문입니다.
이렇게 구분하는 이유는 다중상속의 가능 여부에 따라 용도를 정한 것 같습니다.
자바의 특성상 한 개의 클래스만 상속이 가능하여 해당 클래스의 구분을 추상클래스 상속을 통해 해결하고, 할 수 있는 기능들을 인터페이스로 구현합니다.
추상 클래스는 extends(기능 확장의 느낌) 키워드 그대로 자신의 기능들을 하위 클래스로 확장시키는 것으로 볼 수 있습니다.
인터페이스는 implements(실행하는 기능 구현의 느낌) 키워드처럼 인터페이스에 정의된 메서드를 각 클래스의 목적에 맞게 동일한 기능으로 구현하는 것을 볼 수 있습니다. 즉, 구현하는 객체가 같은 동작을 한다는 것을 보장하기 위함입니다.
'Java' 카테고리의 다른 글
[Kotlin] Data Class란 ? 🤨 (0) | 2024.02.22 |
---|---|
[Java] 오버로딩(Overloading) & 오버라이딩(Overriding) ✌️ (0) | 2024.02.11 |
[Java] Call by value, Call by reference 차이 🤚 (0) | 2024.01.31 |
[Kotlin] 리스트 정렬(sort, sortBy, sortWith) 😙 (0) | 2024.01.27 |
[Java] JVM 이란 ? 🤠 (0) | 2024.01.07 |