추상 클래스(Abstract Class)란 무엇인가?
추상 클래스(Abstract Class)는 객체지향 프로그래밍(OOP)에서 공통된 특성을 가지는 클래스들의 기본 구조를 정의하는 데 사용되는 중요한 개념입니다. 추상 클래스는 클래스 설계 시 다형성과 재사용성을 높여주며, 이를 활용하여 공통된 동작을 여러 하위 클래스에서 일관되게 구현할 수 있습니다.
1. 추상 클래스란?
추상 클래스는 하나 이상의 추상 메서드를 포함할 수 있는 클래스입니다. 추상 메서드는 메서드의 시그니처(이름, 반환 타입, 매개변수 목록)만 정의하고, 실제 구현은 하위 클래스에서 제공됩니다. 추상 클래스는 그 자체로는 인스턴스화할 수 없으며, 반드시 이를 상속받은 구체적인 하위 클래스에서 인스턴스화가 가능합니다.
2. 추상 클래스의 특징
- 추상 메서드(Abstract Method):
- 추상 클래스 내에 선언되는 메서드로, 메서드의 선언부만 있고 구현부는 없습니다.
- 하위 클래스는 반드시 이 추상 메서드를 구현해야 합니다.
- 일반 메서드(Concrete Method):
- 추상 클래스 내에는 구현된 일반 메서드도 포함될 수 있습니다.
- 하위 클래스는 이 일반 메서드를 그대로 상속받아 사용할 수 있으며, 필요에 따라 오버라이딩할 수도 있습니다.
- 멤버 변수:
- 추상 클래스는 일반 클래스처럼 멤버 변수를 가질 수 있습니다. 이 멤버 변수는 상태를 유지하며, 하위 클래스에서 상속받아 사용할 수 있습니다.
- 인스턴스화 불가능:
- 추상 클래스는 인스턴스화할 수 없습니다. 즉, new 키워드를 사용하여 객체를 생성할 수 없습니다.
- 인스턴스화를 위해서는 추상 클래스를 상속받은 하위 클래스에서 구체적인 구현을 제공해야 합니다.
- 단일 상속:
- 자바에서는 한 클래스가 단 하나의 부모 클래스를 상속받을 수 있으며, 추상 클래스도 마찬가지로 단일 상속만 가능합니다. 따라서 한 클래스는 오직 하나의 추상 클래스를 상속받을 수 있습니다.
3. 추상 클래스를 사용하는 이유
- 공통된 동작의 재사용:
- 여러 클래스에서 공통적으로 사용되는 동작이나 속성을 추상 클래스에서 정의하고, 이를 하위 클래스에서 상속받아 사용함으로써 코드의 중복을 줄일 수 있습니다.
- 다형성 구현:
- 추상 클래스는 다형성을 구현하는 데 유용합니다. 상위 클래스의 타입으로 다양한 하위 클래스 객체를 참조할 수 있으며, 각 하위 클래스는 상위 클래스에서 정의된 메서드를 자신만의 방식으로 구현할 수 있습니다.
2-1
abstract class Animal {
abstract void sound(); // 추상 메서드
}
=====================================
2-2
abstract class Animal {
void sleep() {
System.out.println("자야지");
}
}
=====================================
2-4
abstract class Animal {
abstract void sound();
}
class Dog extends Animal {
void sound() {
System.out.println("Bark!");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Dog(); // 가능
Dog dog = new Dog(); // 가능
// Animal animal = new Animal(); // 오류: 추상 클래스는 인스턴스화할 수 없음
}
}
=====================================
3-1
abstract class Animal {
void breathe() {
System.out.println("헥헥");
}
abstract void sound();
}
class Dog extends Animal {
void sound() {
System.out.println("왈왈");
}
}
class Cat extends Animal {
void sound() {
System.out.println("야옹");
}
}
=====================================
3-2
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
dog.sound(); // 출력: 왈왈
cat.sound(); // 출력: 야옹
}
}
인터페이스(Interface)란 무엇인가?
인터페이스(Interface)는 객체지향 프로그래밍(OOP)에서 중요한 개념으로, 클래스가 특정 기능을 반드시 구현하도록 강제하는 계약(Contract) 역할을 합니다. 인터페이스는 구현 방법을 정의하지 않고, 오직 수행해야 할 동작(메서드)을 명시함으로써, 클래스 간의 일관성을 유지하고 다형성을 촉진합니다.
1. 인터페이스란?
인터페이스는 클래스가 구현해야 할 메서드의 집합을 정의하는 일종의 청사진입니다. 인터페이스 자체는 메서드의 시그니처(이름, 반환 타입, 매개변수 목록)만을 포함하며, 실제 구현은 이를 구현하는 클래스에서 제공됩니다. 자바에서 인터페이스는 interface 키워드를 사용하여 정의합니다.
2. 인터페이스의 특징
- 추상 메서드(구현부가 없는 메서드):
- 인터페이스 내의 모든 메서드는 기본적으로 추상적이며, 구현부를 가지지 않습니다. 구현하는 클래스는 이 메서드들을 반드시 구현해야 합니다.
- 다중 상속 가능:
- 자바에서 클래스는 단일 상속만 가능하지만, 인터페이스는 다중 상속이 가능합니다. 즉, 한 클래스가 여러 인터페이스를 구현할 수 있습니다. 이를 통해 다양한 기능을 클래스에 추가할 수 있습니다.
- 상수(final static 변수):
- 인터페이스는 상태를 가질 수 없지만, 상수를 정의할 수 있습니다. 인터페이스 내에서 선언된 변수는 기본적으로 public static final로 간주됩니다.
- 구현 강제성:
- 인터페이스를 구현하는 클래스는 인터페이스에서 정의된 모든 추상 메서드를 구현해야 합니다. 만약 하나라도 구현하지 않으면, 해당 클래스도 추상 클래스로 선언해야 합니다.
2-1
interface Animal {
void sound(); // 추상 메서드
}
=====================================
2-2
interface Jumper {
void jump();
}
interface Swimmer {
void swim();
}
class Duck implements Jumper, Swimmer {
public void jump() {
System.out.println("뛰다");
}
public void swim() {
System.out.println("수영하다");
}
}
=====================================
2-3
interface Constants {
int MAX_SPEED = 100; // public static final int MAX_SPEED = 100;
}
=====================================
2-4
interface Animal {
void sound();
// 디폴트 메서드
default void breathe() {
System.out.println("헥헥");
}
// 정적 메서드
static void info() {
System.out.println("동물들의 인터페이스");
}
}
=====================================
2-5
class Dog implements Animal {
@Override
public void sound() {
System.out.println("왈왈");
}
}
3. 인터페이스를 사용하는 이유
- 다형성 구현:
- 인터페이스를 사용하면 다양한 클래스에서 동일한 인터페이스를 구현하도록 강제함으로써, 다형성을 쉽게 구현할 수 있습니다. 예를 들어, 여러 클래스가 동일한 인터페이스를 구현하고 있다면, 해당 인터페이스 타입으로 객체를 참조하여 동적으로 메서드를 호출할 수 있습니다.
- 계약 기반 설계:
- 인터페이스는 클래스 간의 계약을 정의합니다. 이를 통해 클래스는 특정 인터페이스를 구현함으로써 해당 기능을 반드시 제공해야 합니다. 이는 큰 규모의 프로젝트에서 팀 간 협업 시 매우 유용하며, 각 팀이 자신이 담당하는 부분을 계약에 따라 구현할 수 있습니다.
- 유연한 설계:
- 인터페이스를 사용하면 클래스 설계를 유연하게 할 수 있습니다. 클래스가 특정 인터페이스를 구현함으로써 여러 역할을 수행할 수 있으며, 코드의 재사용성이 높아집니다. 예를 들어, 한 클래스가 여러 인터페이스를 구현하여 다양한 기능을 조합할 수 있습니다.
- 디커플링(Decoupling):
- 인터페이스를 사용하면 클래스 간의 결합도를 낮출 수 있습니다. 구현 클래스의 구체적인 내용을 알 필요 없이, 인터페이스만으로 다른 클래스와 상호작용할 수 있기 때문에, 코드의 유연성과 유지보수성이 크게 향상됩니다.
interface Animal {
void sound();
}
class Dog implements Animal {
public void sound() {
System.out.println("왈왈");
}
}
class Cat implements Animal {
public void sound() {
System.out.println("야옹");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
dog.sound(); // 출력: 왈왈
cat.sound(); // 출력: 야옹
}
}
'CS 지식' 카테고리의 다른 글
동기 ,비동기 처리 (0) | 2024.09.02 |
---|---|
SOLID 원칙 (0) | 2024.09.01 |
오버로딩과 오버라이딩 (0) | 2024.08.15 |
MVC 패턴 (0) | 2024.08.11 |
객체 지향 (0) | 2024.08.01 |