abstract
는 Java에서 추상화(Abstraction)를 구현하는 데 사용되는 키워드로, 클래스 또는 메서드에 적용됩니다. 이를 통해 코드의 공통적인 구조를 정의하고, 세부적인 구현은 하위 클래스에서 처리하도록 강제할 수 있습니다. 아래에서 추상 클래스, 추상 메서드, 그리고 추상 변수에 대해 자세히 설명하겠습니다.
1. 추상 클래스 (Abstract Class)
1.1. 정의
- 추상 클래스는
abstract
키워드로 선언된 클래스입니다. - 직접 객체를 생성할 수 없으며, 상속을 통해 자식 클래스가 이를 구현해야 합니다.
- 공통된 동작과 구체적인 동작을 함께 정의할 수 있습니다.
- 추상 클래스는 추상 메서드뿐만 아니라 일반 메서드도 포함할 수 있습니다.
1.2. 특징
인스턴스화 불가: 추상 클래스는 직접 객체를 생성할 수 없고, 반드시 자식 클래스를 통해 사용해야 합니다.
abstract class Animal {} Animal obj = new Animal(); // 컴파일 에러
상속을 통해 사용: 추상 클래스는 자식 클래스에서 상속받아 구체적인 동작을 정의합니다.
구현의 강제성: 추상 클래스에 포함된 추상 메서드는 자식 클래스에서 반드시 구현해야 합니다.
멤버 구성:
- 추상 메서드와 구현된 메서드를 모두 포함할 수 있음.
- 인스턴스 변수, static 변수, 생성자 등을 포함 가능.
1.3. 예시
abstract class Animal {
String name; // 인스턴스 변수
Animal(String name) { // 생성자
this.name = name;
}
void sleep() { // 일반 메서드
System.out.println(name + " is sleeping.");
}
abstract void sound(); // 추상 메서드
}
class Dog extends Animal {
Dog(String name) {
super(name);
}
@Override
void sound() {
System.out.println("Bark!");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog("Buddy");
dog.sleep(); // 출력: Buddy is sleeping.
dog.sound(); // 출력: Bark!
}
}
분석
Animal
클래스는 추상 클래스이며, 직접 객체를 생성할 수 없음.sound
메서드는 추상 메서드로, 자식 클래스인Dog
에서 반드시 구현.- 공통 동작(
sleep
)은 추상 클래스에 정의하여 코드 중복을 줄임.
2. 추상 메서드 (Abstract Method)
2.1. 정의
- 추상 메서드는 메서드의 선언부만 존재하고, 구현부가 없는 메서드입니다.
abstract
키워드를 사용하여 선언하며, 구현은 자식 클래스에서 이루어집니다.- 추상 메서드는 반드시 추상 클래스 또는 인터페이스에 포함되어야 합니다.
2.2. 특징
- 구현 강제: 추상 메서드는 자식 클래스에서 반드시 재정의(오버라이딩)해야 합니다.
- 메서드 시그니처만 정의: 동작의 공통된 인터페이스를 제공하며, 세부 구현은 자식 클래스에 맡김.
- 추상 클래스 내에서만 선언 가능:
- 추상 메서드는 추상 클래스가 아닌 일반 클래스에 선언할 수 없습니다.
2.3. 예시
abstract class Shape {
abstract void draw(); // 추상 메서드
}
class Circle extends Shape {
@Override
void draw() {
System.out.println("Drawing a circle");
}
}
class Rectangle extends Shape {
@Override
void draw() {
System.out.println("Drawing a rectangle");
}
}
public class Main {
public static void main(String[] args) {
Shape shape1 = new Circle();
Shape shape2 = new Rectangle();
shape1.draw(); // 출력: Drawing a circle
shape2.draw(); // 출력: Drawing a rectangle
}
}
분석
draw
메서드는 추상 메서드로,Shape
클래스에서는 구현되지 않았지만, 자식 클래스에서 각각의 형태에 맞게 구현.
3. 추상 변수 (Abstract Variable)
3.1. 개념
- Java에서는 추상 변수라는 개념은 존재하지 않음. 대신 추상 클래스나 인터페이스에서는 상수(static final)를 정의하거나, 인스턴스 변수를 정의하여 자식 클래스에서 사용.
- 인터페이스에서는 모든 변수가
public static final
로 선언됨.
3.2. 추상 클래스에서 변수 사용
- 추상 클래스에서는 일반 클래스처럼 인스턴스 변수, static 변수를 선언 가능.
abstract class Animal {
String name; // 인스턴스 변수
static int count = 0; // static 변수
}
3.3. 인터페이스에서 변수 사용
- 인터페이스의 변수는 암묵적으로
public static final
로 선언되며, 값을 반드시 초기화해야 함.
interface Constants {
int MAX_VALUE = 100; // public static final
}
public class Main {
public static void main(String[] args) {
System.out.println(Constants.MAX_VALUE); // 출력: 100
}
}
4. 추상 클래스와 인터페이스 비교
특징 | 추상 클래스 | 인터페이스 |
---|---|---|
키워드 | abstract |
interface |
객체 생성 | 불가능 | 불가능 |
메서드 | 추상 메서드와 일반 메서드 포함 가능 | 모든 메서드는 추상 메서드 (Java 8 이후 default/static 가능) |
변수 | 일반 변수, static 변수 포함 가능 |
public static final 상수만 포함 |
다중 상속 | 불가능 (단일 상속만 가능) | 가능 |
사용 목적 | 공통 코드와 세부 구현을 일부 제공 | 구현 강제, 다형성을 위한 공통 인터페이스 제공 |
5. 추상 클래스의 활용
- 템플릿 메서드 패턴:
- 알고리즘의 공통적인 뼈대를 정의하고, 세부적인 구현은 자식 클래스에서 오버라이딩.
- 코드 재사용:
- 공통 동작은 추상 클래스에 정의하고, 중복을 줄임.
- 확장 가능성:
- 새로운 기능 추가 시 추상 클래스만 수정하면 되므로 유지보수가 용이.
6. 결론
- 추상 클래스는 공통적인 동작과 구조를 정의하고, 구체적인 구현은 자식 클래스에서 하도록 강제하는 도구.
- 추상 메서드는 구현 강제를 통해 다형성을 실현하며, 메서드의 구조를 고정.
- 추상 변수는 직접적인 개념으로 존재하지 않지만, 추상 클래스와 인터페이스에서 각기 다른 방식으로 변수 정의 가능.
추상화를 통해 코드의 확장성, 유지보수성, 재사용성을 크게 향상시킬 수 있습니다.
추상과 상속의 상관관계
추상(Abstraction)과 상속(Inheritance)은 객체 지향 프로그래밍(OOP)에서 서로 밀접하게 연관된 개념입니다.
이 두 개념의 상관관계를 이해하기 위해 각각의 본질과 역할을 살펴보고, 구체적인 연관성을 설명합니다.
1. 추상(Abstraction)의 개념
정의
- 추상화는 객체의 복잡성을 줄이고, 핵심적인 정보만 표현하는 것을 의미합니다.
- 추상화는 구체적인 구현은 감추고, 필요한 인터페이스(기능)를 정의하는 데 초점을 맞춥니다.
- Java에서는 추상 클래스(abstract class)와 인터페이스(interface)를 통해 구현됩니다.
목적
- 공통적인 동작(메서드)을 정의하고, 구체적인 구현은 자식 클래스에 맡김.
- 코드를 재사용 가능하고, 유지보수성을 높이며, 다형성을 지원.
2. 상속(Inheritance)의 개념
정의
- 상속은 한 클래스가 다른 클래스의 속성과 메서드를 물려받는 것을 의미합니다.
- 부모 클래스(슈퍼 클래스)의 모든 멤버(변수와 메서드)를 자식 클래스(서브 클래스)가 상속받아 사용하거나, 확장(override)하여 새로운 기능을 추가할 수 있습니다.
목적
- 코드의 재사용성을 높이고, 클래스 간 계층 구조를 형성.
- 상위 클래스에서 공통 기능을 정의하고, 하위 클래스에서 구체적으로 구현.
3. 추상과 상속의 상관관계
추상과 상속은 다형성(Polymorphism)과 코드 재사용성을 중심으로 강하게 연결되어 있습니다.
3.1. 추상화는 상속을 전제로 설계됨
- 추상 클래스는 상속을 통해 사용됩니다.
- 추상 클래스는 객체를 직접 생성할 수 없으며, 자식 클래스가 이를 상속받아 구체적으로 구현해야 의미가 있습니다.
- 예:
abstract
키워드를 사용한 메서드는 자식 클래스에서 반드시 구현(override)되어야 함.
예시
abstract class Animal {
abstract void sound(); // 추상 메서드: 구현 없음
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Bark");
}
}
class Cat extends Animal {
@Override
void sound() {
System.out.println("Meow");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog(); // 상속을 통해 추상 클래스 사용
Animal cat = new Cat();
dog.sound(); // 출력: Bark
cat.sound(); // 출력: Meow
}
}
- 분석:
Animal
은 추상 클래스이며, 객체 생성 불가.Dog
와Cat
은 상속을 통해 추상 메서드를 구현하여 구체화.
3.2. 추상화는 상속의 구체적인 활용 사례
- 상속은 코드 재사용에 초점이 맞춰져 있지만, 추상화를 통해 상속을 더욱 체계적으로 활용할 수 있습니다.
- 부모 클래스에서 공통 동작의 인터페이스(구조)를 정의하고, 자식 클래스에서 구체적으로 구현함으로써 일관성과 확장성을 제공.
상속만 사용한 경우
class Animal {
void sound() {
System.out.println("Generic Animal Sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Bark");
}
}
- 여기서는 부모 클래스에서
sound
의 동작이 이미 구현되어 있어, 자식 클래스에서 오버라이딩하지 않아도 동작 가능. - 반면, 추상 클래스를 사용하면
sound
를 구현하지 않는 클래스는 컴파일 에러가 발생하므로, 모든 자식 클래스가 해당 메서드를 반드시 정의하도록 강제.
추상화로 구현 강제
abstract class Animal {
abstract void sound(); // 추상화로 모든 자식 클래스에 구현 강제
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Bark");
}
}
class Cat extends Animal {
@Override
void sound() {
System.out.println("Meow");
}
}
- 추상화는 설계상 구현 강제성을 통해 자식 클래스에서 일관된 인터페이스를 제공하게 만듦.
3.3. 추상화와 상속의 목적
추상화 | 상속 |
---|---|
공통된 기능의 인터페이스(구조)를 정의 | 부모 클래스의 기능을 재사용하고 확장 |
구현 강제 → 코드의 일관성 확보 | 코드의 중복 제거 → 유지보수성 향상 |
객체의 구체적인 동작은 숨기고 필요한 것만 제공 | 상위 클래스의 동작을 재정의(Override) 가능 |
4. 추상화와 상속의 동시 사용 사례
템플릿 메서드 패턴
- 추상 클래스에서 알고리즘의 뼈대(템플릿)를 정의하고, 일부 세부 구현은 자식 클래스에서 정의하도록 강제.
- 부모 클래스는 공통 동작을 정의하고, 자식 클래스는 특정 동작만 변경 가능.
예시
abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
// 템플릿 메서드
public final void play() {
initialize();
startPlay();
endPlay();
}
}
class Football extends Game {
@Override
void initialize() {
System.out.println("Football Game Initialized!");
}
@Override
void startPlay() {
System.out.println("Football Game Started!");
}
@Override
void endPlay() {
System.out.println("Football Game Ended!");
}
}
public class Main {
public static void main(String[] args) {
Game game = new Football();
game.play();
}
}
분석
- 추상 클래스
Game
은 템플릿 메서드(play
)를 정의. - 자식 클래스
Football
은 추상 메서드를 구현하여 구체적인 동작 정의. play
메서드는 부모 클래스에서 공통된 알고리즘을 제공하므로, 자식 클래스의 구현과 상관없이 호출 가능.
5. 결론
- 추상화와 상속의 관계:
- 추상 클래스는 상속을 전제로 설계되며, 상속을 통해 추상 메서드와 공통 동작을 구현하고 확장.
- 상속만 사용하면 코드 재사용은 가능하지만, 추상화를 통해 구현 강제성과 일관성을 추가로 확보 가능.
- 상호 보완적 역할:
- 추상화는 설계를 체계적으로 만들고, 상속이 이를 구체화함.
- 두 개념은 다형성(Polymorphism)의 기반을 제공하여 객체 지향 설계의 핵심이 됨.
- 결론적 활용:
- 추상화를 통해 상속 관계를 더욱 구조화하고, 유지보수성과 확장성을 강화.
- 적절히 활용하면 코드 재사용성, 유연성, 일관성을 모두 확보할 수 있음.
'자바 > 객체지향 프로그래밍(OOP)' 카테고리의 다른 글
생성자와 객체생성에 대한 이해 (0) | 2025.01.27 |
---|---|
클래스란? (0) | 2025.01.26 |
업캐스팅과 다운캐스팅 상태에서의 변수와 메서드 사용 가능 여부 (0) | 2025.01.23 |
인스턴스 변수 (0) | 2025.01.23 |
객체와 인스턴스 이해 (0) | 2025.01.22 |