
Java는 객체 지향 프로그래밍(OOP) 언어로, OOP의 4가지 주요 요소인 추상화, 캡슐화, 다형성, 상속성을 중심으로 설계되었다. 이 글에서는 마지막으로 추상화(Abstraction)에 대해 알아보자.
추상화(Abstraction)란?
잡한 시스템에서 핵심적인 부분만을 모델링하여 단순화하는 과정이다. 이를 통해 불필요한 세부 사항을 숨기고 중요한 부분만을 강조함으로써 복잡성을 줄이고, 코드를 이해하고 관리하기 쉽게 만든다. 추상화는 주로 추상 클래스(Abstract Class)와 인터페이스(Interface)를 통해 구현된다.
추상 클래스(Abstract Class)
추상 클래스는 하나 이상의 추상 메소드(Abstract Method)를 포함하는 클래스다. 추상 메소드는 구현이 없는 메소드 선언부만을 가지며, 이를 상속받는 하위 클래스에서 반드시 구현해야 한다. 추상 클래스는 객체를 생성할 수 없으며, 주로 공통적인 기능을 제공하고, 하위 클래스에서 구현해야 할 메소드들을 정의하는 데 사용된다.
abstract class Animal {
// 추상 메소드
abstract void sound();
// 일반 메소드
void breathe() {
System.out.println("Breathing...");
}
}
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
dog.breathe(); // Breathing...
cat.breathe(); // Breathing...
}
}
위의 예시에서 Animal 추상 클래스는 추상 메소드 sound()와 일반 메소드 breathe()를 정의하고 있다. Dog와 Cat 클래스는 Animal 클래스를 상속받아 sound() 메소드를 구현한다.
인터페이스(Interface)
인터페이스는 추상 메소드의 집합으로, 클래스가 구현해야 하는 메소드들을 정의한다. 인터페이스는 구현을 가지지 않으며, 다중 상속을 허용한다는 점에서 추상 클래스와 다르다.(하나의 클래스가 여러 개의 인터페이스 상속 가능) 인터
페이스를 구현하는 클래스는 인터페이스에 선언된 모든 메소드를 구현해야 한다. implements 키워드를 통해 구현한다.
특징
인터페이스의 모든 메소드는 추상 메소드다. 모든 메소드에는 public abstract가 붙어야 하기 때문에 생략도 가능하다.
모든 멤버 변수는 상수가 되기에 public static final이다.
interface Animal {
void sound();
void eat();
}
class Dog implements Animal {
@Override
public void sound() {
System.out.println("Bark");
}
@Override
public void eat() {
System.out.println("Dog is eating");
}
}
class Cat implements Animal {
@Override
public void sound() {
System.out.println("Meow");
}
@Override
public void eat() {
System.out.println("Cat is eating");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
dog.sound(); // Bark
dog.eat(); // Dog is eating
cat.sound(); // Meow
cat.eat(); // Cat is eating
}
}
위의 예시에서 Animal 인터페이스는 sound()와 eat() 메소드를 정의하고 있다. Dog와 Cat 클래스는 Animal 인터페이스를 구현하여 모든 메소드를 구현한다.
추상화의 장점
- 복잡성 감소: 추상화를 통해 복잡한 시스템을 단순화하고, 핵심적인 부분에 집중할 수 있다.
- 코드 재사용성 향상: 공통된 기능을 추상 클래스나 인터페이스로 정의하여, 여러 클래스에서 이를 재사용할 수 있다.
- 유지보수성 향상: 추상 클래스나 인터페이스를 통해 코드의 구조를 명확히 하고, 변경이 필요할 때 영향 범위를 최소화할 수 있다.
추상 클래스와 인터페이스의 비교
특징추상 클래스 (Abstract Class)인터페이스 (Interface)
특징 | 추상 클래스(Abstract Class) | 인터페이스(Interface) |
객체 생성 | 불가능 | 불가능 |
다중 상속 | 불가능 (단일 상속만 가능) | 가능 |
메소드 구현 | 구현된 메소드를 가질 수 있음 | 모든 메소드는 추상 메소드 |
접근 제어자 | 모든 접근 제어자 사용 가능 | 기본적으로 public (생략 시 public) |
필드 | 일반 멤버 변수와 static 변수를 가질 수 있음 | static final 변수만 가질 수 있음 |
결론적으로, 인터페이스는 멤버 변수 선언과 메서드 구현을 제한하면서, 메서드 구현 강제에 더욱 집중함 • 또한, 추상 클래스와 달리 다중 구현이 가능하다는 이점이 있다.
인터페이스의 핵심은 역할과 구현의 구분을 명확히 한 것.
자바 8 이후의 인터페이스 변경 사항
1. default 메서드
자바 8 이전에는 인터페이스의 모든 메서드는 public abstract였지만, 자바 8 이후에는 default 메서드를 통해 인터페이스 내에서 메서드를 구현할 수 있게 되었다.
interface Programmable {
String[] getTechStack();
void doProgramming();
default void drinkCoffee() {
System.out.println("Drinking Coffee...");
}
}
2. static 메서드
마찬가지로, 자바 8 이후 인터페이스 내에서 static 메서드를 정의할 수 있게 되었다.
interface Programmable {
String[] getTechStack();
void doProgramming();
static void sayHello() {
System.out.println("Hello Elice!");
}
}
이에 따라 인터페이스도 일부 메서드 구현과 정적 메서드를 가질 수 있게 되었습니다.
