[Practical-Java] 3. Abstract Class와 Interface
in Java on Java Practical
추상 클래스(Abstract Class)
와 인터페이스(Interface)
의 차이점 및 용도로는 추상 클래스와 인터페이스는 모두 다형성(polymorphism) 을 지원하고, 코드 재사용성을 높이며, 설계 원칙을 명확히 하기 위해 사용되지만 목적, 사용 방법 및 기능에 따라 차이가 있다.
1. 추상 클래스와 인터페이스
추상 클래스와 인터페이스는 추상화를 통해 객체지향 설계에서 공통적인 동작이나 계약을 정의하는 데 사용된다. 그리고 추상 클래스와 인터페이스 자체로는 직접 객체화 할 수 없고 구현 클래스를 통해서 객체 생성이 가능하다.
① 공통된 목적
추상화 제공:
- 둘 다 직접적인 객체 생성이 불가능하며, 하위 클래스나 구현체를 통해 동작이 구체화됩니다.
- 추상 클래스는 “공통된 속성과 동작”의 기본 틀을 제공합니다.
- 인터페이스는 “구현해야 할 행동”의 계약을 정의합니다.
② 다형성(Polymorphism) 지원
참조 타입으로 사용 가능:
- 추상 클래스와 인터페이스 모두 부모 타입(추상 클래스 또는 인터페이스)으로 참조하고, 하위 클래스나 구현체에서 다형성을 구현할 수 있다.
abstract class Animal {
abstract void makeSound();
}
interface Flyable {
void fly();
}
class Bird extends Animal implements Flyable {
@Override
void makeSound() {
System.out.println("Chirp!");
}
@Override
public void fly() {
System.out.println("Bird is flying.");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Bird(); // 추상 클래스 타입으로 참조
animal.makeSound();
Flyable flyable = new Bird(); // 인터페이스 타입으로 참조
flyable.fly();
}
}
③ 추상 메서드 포함
구현을 강제:
- 추상 클래스와 인터페이스 모두 추상 메서드를 포함하여 구현체에 특정 메서드의 구현을 강제합니다.
④ 구현체에서 확장/구현 필요
- 추상 클래스는 상속을 통해 확장해야 하고,
- 인터페이스는 구현을 통해 구체적인 동작을 정의해야 합니다.
⑤ 상속 및 구현 관계에서 사용
추상 클래스: 클래스 간의 “is-a” 관계
- 하위 클래스가 상위 클래스의 일종이라는 것을 의미
- 추상 클래스의 공통 속성(필드)과 동작(메서드)을 하위 클래스에서 그대로 사용하거나, 필요에 따라 확장(재정의)
- 추상 클래스는 공통된 속성과 동작을 공유하면서, 특정 클래스 계층의 멤버임을 나타내기 위해 사용
인터페이스: 클래스 간의 “can-do” 관계
- 클래스가 특정 기능을 수행할 수 있음을 보장하는 계약을 의미
- 인터페이스는 특정 행동(메서드)을 구현하도록 클래스를 강제하거나 여러 동작을 조합
- 클래스는 인터페이스를 구현하여 “나는 이 행동을 할 수 있다”는 것을 나타냄
⑥ 설계 원칙 준수
SOLID 원칙을 지원:
- OCP(개방-폐쇄 원칙): 추상 클래스와 인터페이스는 코드 확장성에 기여
- DIP(의존성 역전 원칙): 둘 다 상위 수준의 설계를 통해 구현체와 느슨한 결합(loose coupling)을 지원
⑦ 객체지향 프로그래밍(OOP)에서 필수 요소
- 둘 다 캡슐화(Encapsulation), 다형성(Polymorphism),
추상화(Abstraction)
를 구현하는 데 중요한 역할 - 공통 동작을 정의하여 코드 재사용성을 높이고, 유지보수에 용이하게 함
2. 추상 클래스와 인터페이스 차이점
- 추상 클래스는 멤버 변수를 가질 수 있지만 인터페이스는 멤버 변수를 가질 수 없다. 물론 인터페이스도 static으로 정의된 변수를 내부적으로 선언할 수 있지만 멤버 변수는 선언할 수 없다.
- 클래스를 구현할때 오직 하나의 클래스만을 상속 받을 수 있는 반면에 인터페이스는 여러 개를 상속받거나 구현 할 수 있다.
멤버 변수는 그 객체의 속성을 담기 위한 용도로 사용하는데 메서드 내에 선언 된 지역 변수는 메서드가 종료되면 그 상태를 잃어버리지만 클래스의 멤버 변수는 객체가 유지되는 동안은 속성 상태를 유지하거나 변경할 수도 있는데 인터페이스에 멤버변수가 존재하지 않는다.
추상 클래스와 인터페이스의 선택 기준
1 . 공통 로직 제공 여부
- 공통 로직과 속성을 공유하려면 추상 클래스
- 구현 클래스 간 공통된 동작을 강제하려면 인터페이스
2 . 다중 상속 필요 여부
- 단일 상속으로 계층구조가 필요하면 추상 클래스
- 다중 상속으로 다중 행동을 조합해야 한다면 인터페이스
3 . 설계의 유연성
- 인터페이스는 느슨한 결합으로 기능 확장에 적합.
- 추상 클래스는 강한 결합으로 계층 구조를 명확히 하고 재사용성 증가.
결론
결론은 필드 선언 가능 여부와 다중 구현 가능성 차이로
추상 클래스는 상태(필드)
를 다루고 기본 구현을 제공하는 데 중점 인터페이스는 동작(메서드)
를 정의하고 다중 구현을 지원하는 데 중점
추상 클래스: “IS-A” 관계
- 클래스 간 상속을 통한 공통 로직과 속성을 공유할 때 사용
- 상속 계층에서 공통 동작과 상태를 정의할 때 사용
- 하위 클래스가 반드시 특정 메서드를 구현하도록 강제하며, 일부는 공통 구현 제공
인터페이스: “CAN-DO” 관계
- 다중 상속을 통한 행동(기능)의 계약을 정의할 때 사용
- 클래스를 특정 행동을 강제적으로 구현하도록 만들 때 사용
- 다중 상속이 필요할 때 사용