추상화
- 추상화는 객체에서 공통된 속성과 기능을 추출하는 것
- 자바에서 추상화는 공통된 속성과 기능을 모아서 추상클래스(Abstract Class)나 인터페이스(Interface)를 정의하는 것이다.
- 공통 속성은 변수나 상수로 표현하고, 기능은 추상 메소드로 표현한다.
- 추상화를 통해서 하위 클래스들이 구현해야 할 공통 기능을 정의할 수 있다.
추상메소드
추상메소드를 상속 받았다면 반드시 메소드 재정의를 통해서 구현부가 있는 메소드로 만들어야 한다.
⇒ 자식 클래스에 구현을 강제하는 메소드
note
- 공통기능을 추상화하는 메소드
- 구현부가 없는 메소드 ⇒ 설계만 해 놓은 미완성 메소드
- 추상클래스와 인터페이스, enum에만 정의할 수 있다.
- 일반 클래스(구현 클래스)는 추상메소드를 보유할 수 없다.
Abstract Class 🥬
추상클래스
public abstract class Sample {
// 추상 메소드
abstract void test1();
// 구현 메소드
void test3() {
수행문;
}
}
public class Car extends Sample {
void test1(){
...구현 로직
}
}
- 추상 클래스는 abstract 키워드가 붙은 클래스
- 추상 메소드 + 구현 메소드를 둘 다 갖는다.
- 미완성 설계도(밑그림과 어느 정도 구현됨) ⇒ 미완성 메소드를 포함
- 추상 클래스는 new 키워드를 사용해서 객체 생성할 수 없다.
- 구현 클래스는 상속을 통해서 구현해야 한다.
구현 클래스와 차이
- 구현부가 없는 메소드를 가질 수 있다는 것이 차이점
구현 클래스와 공통점
- 다른 클래스 처럼 생성자, 멤버변수, 메소드를 넣을 수 있다.
- extends, implements 둘 다 받을 수 있다.
사용목적
- 모든 하위 클래스가 동일한 동작하는 기능을 추상 클래스에서 구현해서 상속 시킴으로써 하위 클래스의 구현부담을 경감시킨다.
- 추상 클래스를 사용(extends)하면 인터페이스에서 바로 implements한 것 보다 구현 클래스의 구현 부담이 줄어든다.
- 구현클래스마다 구체적인 구현 내용이 다른 것은 구현부가 없는 메소드상태로 두면, 각각의 구현클래스마다 자신에게 맞게 구현부가 없는 메소드를 재정의하게 한다.
⇒ 구현 내용이 동일한 기능은 추상 클래스에서 구현하여 자식 클래스에게 상속하여 사용한다.
⇒ 구현 내용이 다른 것(abstract)만 구현클래스에서 재정의하면 된다.
Interface
P.S. 자바8 이전 문법 기준
- 상수, 추상메소드만 보유할 수 있다.
- 추상클래스보다 추상화 정도가 높아서 구현부를 갖춘 메서드나 멤버 변수를 구성원으로 가질 수 없다.
- new연산자를 사용해서 객체를 생성할 수 없다.
- 다중 상속을 지원한다.
- 기본 설계도(밑그림만 있는)
정의
- 구현 클래스가 반드시 구현할 기능을 정의하는 표준(기준, 스펙)
- 구현 클래스가 재정의할 기능에 대한 명세서
- 구현부가 없는 추상메소드는 구현클래스가 재정의할 기능에 대한 명세
- 구현 클래스가 구현할 기능을 지정
- 구현메소드의 접근제한자, 반환타입, 메소드명, 매개변수의 타입을 어떻게 정의해야 하는지 알려주는 것
- 구현 클래스들의 사용법이 똑같아진다.
- 인터페이스와 구현클래스들의 메소드 선언부가 같다.
- 구현내용은 다를 수 있다.
사용목적
- 사용방법이 똑같은 객체를 만들려고
- 객체관의 관계를 느슨하게 만들려고
- 다른 클래스로 교체할 때, 수정할 코드가 줄어든다.
응집도는 높고 결합성은 낮게 = 웹의 확장성이 좋다. ⭐⭐⭐⭐⭐
default Methods
인터페이스 안에서 구현이 있는 메소드를 선언할 수 있게 해줌
java 8 이상에서 사용 가능한 기능
public interface Vehicle {
public default void doSomething(int n) {
System.out.println("doSomething(Vehicle)");
}
}
이 메소드를 자식 클래스에서 반드시 구현할 필요가 없어짐 또는 override할 수 있음
만든이유?
- 기존에 존재하던 인터페이스를 이용하여서 구현된 클래스를 만들고 사용하고 있는데
- 인터페이스를 보완하는 과정에서 추가적으로 구현해야 할 혹은 필수적으로 존재해야 할 메소드가 생김
- 인터페이스에 메서드를 하나만 추가해도 → 그 인터페이스를 구현하던 모든 클래스에서
- 새 메서드를 강제로 구현해야된다.
- 이런 경우 default 메소드를 추가하게 된다면 기존 구현체들은 자동으로 기본 구현을 상속받으니 호환성을 유지할 수 있다.
구현 클래스와 인터페이스 관계
- 구현 클래스는 다중 구현이 가능하다. = 구현 클래스는 하나 이상의 인터페이스를 구현한 클래스다.
- 구현클래스는 구현부가 없는 추상메소드를 포함할 수 없다.
- 클래스는 인터페이스를 implements 해서 인터페이스를 구현한다.
- 인터페이스는 class를 extends 할 수 없고, 오직 다른 인터페이스만 extends 할 수 있다.
- 만약 구현부가 없는 메소드를 상속받으면 무조건 재정의 해야 한다.
- 구현 클래스는 인터페이스에 정의된 구현부가 없는 메소드를 전부 재정의한 클래스다.
- 구현클래스에는 구현부가 없는 메소드가 하나도 없다.
- 재정의를 강제
- 구현클래스는 implements(구현하다, 구체화하다) 키워드를 사용해서 자신이 구현할 기능이 선언되어 있는 인터페이스들을 지정할 수 있다.
public class 구현클래스 implements 인터페이스1, 인터페이스2, 인터페이스3, ..., 인터페이스N {
// 각 인터페이스에 정의된 구현부가 없는 추장메소드를 전부 재정의 한다.
// 구현부가 없는 추상메소드가 하나라도 재정의되지 않으면 구현클래스는 컴파일 오류가 발생
}
- 인터페이스끼리 상속할 수 있다. interface Car extends Movable, Stop { }
- 특정 인터페이스를 구현한 구현클래스들은 언제나 동일한 메소드 사용법을 가지고 있다. → 동작은 다르다.(구현부)
- 부모 인터페이스 타입의 참조 변수로 자식 객체를 참조할 수 있다.
- 상속과 구현을 동시 가능 ⇒ public class A extends B implements C { ... }
- 클래스의 상속은 단일 상속
- 클래스 vs 클래스(일반/추상 상관 없음) → extends
- 클래스 vs 인터페이스 → implements
- 인터페이스 vs 인터페이스 → extends
클래스와 인터페이스의 상속
- interface 간의 관계는 다중 상속, class의 간의 관계는 단일 상속 관계
- 클래스는 단일 상속이 가능하다.
- 여러개의 부모에서 같은 메소드가 있을 때 다중 상속의 모호성으로 컴파일 에러가 발생한다.
- 여러 부모가 같은 super을 공유하는 경우 어떤 순서로 초기화할지 모호하므로 컴파일 에러가 발생한다.
- 인터페이스는 다중 상속이 가능하다.
- 단, 같은 명의 메소드가 있을 때 리턴 타입이 다를 때(상하위 관계가 아닐 때) 컴파일 에러
- 같은 명의 필드가 있을 때 사용시 인터페이스의 이름을 붙인다.
- Default메소드가 중복되는 경우는 반드시 그 메소드를 오버라이드하는 것으로 모호성을 방지한다.
- 어떤 인터페이스의 메소드인지 직접 명시해야 된다.