—What are abstraction, abstract class, interface in Java
✅ 추상화(Abstraction)란?
자바의 추상화는 객체 지향 프로그래밍에서 중요한 개념 중 하나로, 복잡한 시스템이나 개념을 단순화하고 필요한 부분에 집중할 수 있도록 하는 과정입니다. 쉽게 말해서 공통적인 부분은 추상적으로 모으고, 개별적인 부분은 구체적으로 따로 만드는 것입니다.
공통된 특징과 동작을 추상화하여 나타내고, 구체적인 내용은 이를 구현한 객체를 통해서 나타냅니다. 객체 지향 프로그래밍에서는 추상 클래스와 인터페이스를 통해 추상화를 구현합니다.
추상화는 세부적인 내용을 숨기고 중요한 개념이나 특징에 집중함으로써 복잡성을 감소시키는데 도움을 줍니다. 이를 통해 소프트웨어 개발자는 복잡한 시스템을 더 쉽게 이해하고, 유지 보수하고, 확장할 수 있습니다. 객체 지향 프로그래밍의 원칙을 따르고 코드의 재사용성, 유연성, 유지 보수성을 높이는데 기여합니다.
추상화는 객체 지향 프로그래밍의 핵심 원칙 중 하나인 "추상화와 캡슐화(Encapsulation)"와 밀접한 관련이 있습니다. 추상화는 복잡성을 감소시키고 중요한 개념에 집중할 수 있도록 코드와 데이터를 캡슐화하여 외부로부터의 접근을 제한하는데 기여합니다.
✅ 추상 클래스(Abstract Class)
추상 클래스는 다른 클래스들의 공통된 특성을 나타내기 위해 사용되며, 직접적으로 객체를 생성할 수 없는 클래스입니다. 이는 Abstract Method(추상 메소드)가 있기 때문입니다.
추상 클래스는 일반 클래스와는 달리 하나 이상의 추상 메서드를 포함할 수 있습니다.( 반드시 포함되어야 하는 것은 아니지만 포함하지 않으면 추상 클래스를 만들 이유가 없습니다. )
추상 메서드는 아래 코드와 같이 구현 코드 없이 메서드의 시그니처(이름, 매개변수, 반환타입)만을 정의한 메서드입니다. abstract 키워드를 사용하고, { }에 해당하는 구현부가 없는 메소드입니다. 이러한 추상 메서드는 하위 클래스에서 반드시 구현되어야 합니다.
public abstract void makeSound();
추상 클래스의 목적은 공통된 속성과 동작을 가진 클래스들을 그룹화하고, 코드의 재사용성과 일관성을 높이는 것입니다. 따라서 추상 클래스는 추상 메서드와 일반 메서드를 조합하여 필요에 따라 구현을 갖출 수 있습니다.
// 추상 클래스
abstract class Animal {
// 추상 메서드
public abstract void makeSound();
// 일반 메서드
public void sleep() {
System.out.println("동물이 잠을 잡니다.");
}
}
// Animal 클래스를 상속받은 구체적인 클래스(Concrate Class)
class Dog extends Animal {
// 추상 메서드 구현
@Override
public void makeSound() {
System.out.println("개가 짖습니다.");
}
}
// Animal 클래스를 상속받은 구체적인 클래스(Concrate Class)
class Cat extends Animal {
// 추상 메서드 구현
@Override
public void makeSound() {
System.out.println("고양이가 야옹합니다.");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.makeSound(); // "개가 짖습니다."
dog.sleep(); // "동물이 잠을 잡니다."
Animal cat = new Cat();
cat.makeSound(); // "고양이가 야옹합니다."
cat.sleep(); // "동물이 잠을 잡니다."
}
}
위의 코드에서 Animal
은 추상 클래스입니다. 추상 클래스는 abstract
키워드로 선언되며, 하나 이상의 추상 메서드를 가질 수 있습니다. Animal
클래스는 makeSound()
라는 추상 메서드를 선언하고 있습니다. 추상 클래스를 상속 받아 구현한 클래스를 구체 클래스(Concrete Class), 구현체라고 합니다.
추상 메서드는 구현을 갖지 않으며, 하위 클래스에서 반드시 구현해야 합니다. 따라서 Dog
클래스와 Cat
클래스는 Animal
클래스를 상속받아 makeSound()
메서드를 구현합니다.
Animal
클래스에는 일반 메서드인 sleep()
도 있습니다. 이는 추상 클래스에서 구현된 일반적인 기능을 제공하는 메서드입니다. sleep()
메소드는 구현 클래스에서 오버라이드해서 사용할 수도 있고, 상속 받은 클래스의 정의된 메소드를 그대로 사용할 수도 있습니다.
✅ 왜 인터페이스가 생겨났을까?
인터페이스가 만들어진 주요한 이유 중 하나는 다중 상속의 제약을 극복하기 위해서입니다. 다중 상속은 하나의 클래스가 여러 개의 클래스로부터 상속받는 것을 의미합니다. 하지만 다중 상속은 일부 경우에 복잡성과 모호성을 초래할 수 있습니다.
자바 언어는 다중 상속을 지원하지 않는 선택을 한 이유로 클래스 간의 이름 충돌, 다이아몬드 상속 문제 등을 예방하고 코드의 가독성과 유지 보수성을 향상시키기 위함입니다. 다중 상속을 허용하면 클래스 간의 관계가 복잡해지고 코드 충돌이 발생할 수 있습니다.
인터페이스는 이러한 다중 상속의 제약을 극복하기 위한 해결책으로 도입되었습니다. 인터페이스는 클래스가 특정 기능 집합을 구현하도록 요구하는 계약이므로, 클래스가 여러 개의 인터페이스를 동시에 구현함으로써 다중 구현을 가능하게 합니다. 따라서 다중 상속이 필요한 경우에는 클래스가 여러 개의 인터페이스를 구현하여 다중 구현을 통해 기능을 확장할 수 있습니다.
인터페이스는 다중 구현을 통해 클래스들 간의 관계를 유연하게 형성할 수 있으며, 클래스 간의 결합도를 낮추고 코드 재사용성과 확장성을 향상시킬 수 있는 장점이 있습니다.
✅ 인터페이스(Interface)
인터페이스는 자바에서 추상화를 실현하기 위한 중요한 개념입니다. 인터페이스는 일련의 추상 메서드와 상수들의 집합으로 정의됩니다. 클래스와 달리 다중 상속을 지원하며, 구현을 갖지 않는 추상 메서드로만 이루어져 있습니다.
➡️인터페이스는 다음과 같은 특징을 가지고 있습니다:
- 추상 메서드
인터페이스는 추상 메서드를 선언하며, 이들은 구현을 갖지 않습니다. 추상 메서드는 인터페이스를 구현하는 클래스에서 반드시 구체적인 구현을 제공해야 합니다.
- 다중 상속
클래스는 단일 상속만을 지원하지만, 인터페이스는 다중 상속(다중 구현)을 지원합니다. 클래스는 하나의 클래스만 상속받을 수 있지만, 여러 인터페이스를 구현할 수 있습니다. 이를 통해 클래스는 여러 개의 인터페이스로부터 다양한 특성과 동작을 상속받을 수 있습니다.
- 구현을 갖지 않는 메서드
인터페이스의 추상 메서드는 구현을 갖지 않습니다. 대신, 해당 인터페이스를 구현하는 클래스에서 메서드의 구체적인 구현을 제공해야 합니다. 이를 통해 인터페이스는 클래스 간의 일관성 있는 메서드 시그니처를 보장합니다. 클래스가 인터페이스를 구현할 때, 모든 인터페이스의 추상 메서드를 구현해야 합니다.
- 상수
인터페이스는 상수를 선언할 수 있습니다. 이는 인터페이스 내에서 사용되는 고정된 값들을 나타냅니다. 상수는 자동으로 `public static final`로 선언되며, 클래스에서 접근할 때는 인터페이스 이름을 통해 접근해야 합니다.
👉 이러한 특징을 가진 인터페이스는 코드의 재사용성, 다형성, 유연성을 증가시키고, 클래스 간의 결합도를 낮춰줍니다. 다양한 클래스들이 공통된 동작을 가지도록 정의된 인터페이스를 구현함으로써, 인터페이스를 통해 다양한 객체를 일관성 있게 다룰 수 있습니다.
- 여러 개의 인터페이스를 구현(다중 구현)
// 인터페이스 1 interface Walkable { void walk(); } // 인터페이스 2 interface Swimmable { void swim(); } // 여러 개의 인터페이스를 구현하는 클래스 class Human implements Walkable, Swimmable { public void walk() { System.out.println("사람이 걷습니다."); } public void swim() { System.out.println("사람이 수영합니다."); } } // Human 클래스의 인스턴스 생성 및 사용 public class Main { public static void main(String[] args) { Human person = new Human(); person.walk(); // "사람이 걷습니다." 출력 person.swim(); // "사람이 수영합니다." 출력 } }
위의 코드에서 Walkable과 Swimmable 두 개의 인터페이스가 정의되어 있습니다. 그리고 Human 클래스는 이러한 인터페이스들을 구현하는 클래스입니다.
Human 클래스는 Walkable과 Swimmable 인터페이스에서 정의된 메서드인
walk()
와swim()
을 구현합니다. 각 메서드는 해당 동작을 구체적으로 정의하고 출력합니다.Main 클래스에서는 Human 클래스의 인스턴스를 생성하고, 해당 인스턴스의 메서드를 호출하여 동작을 수행합니다. 출력 결과로는 "사람이 걷습니다."와 "사람이 수영합니다."가 출력됩니다.
이를 통해 여러 개의 인터페이스를 구현하는 클래스를 만들고, 해당 인터페이스에서 정의된 메서드를 구현하고 사용할 수 있습니다.
- 상속과 구현 동시 사용
// 추상 클래스 abstract class Animal { public abstract void sound(); // 추상 메서드 public void eat() { System.out.println("동물이 먹는 중입니다."); } } // 인터페이스 interface Flyable { void fly(); // 추상 메서드 } // Animal 클래스를 상속받고 Flyable 인터페이스를 구현한 구체 클래스 class FlyingDog extends Animal implements Flyable { public void sound() { System.out.println("개가 짖습니다."); } public void fly() { System.out.println("개가 날아갑니다."); } } // FlyingDog 클래스의 인스턴스 생성 및 사용 public class Main { public static void main(String[] args) { FlyingDog dog = new FlyingDog(); dog.sound(); // "개가 짖습니다." 출력 dog.eat(); // "동물이 먹는 중입니다." 출력 dog.fly(); // "개가 날아갑니다." 출력 } }
위의 코드에서 FlyingDog 클래스는 Animal 추상 클래스를 상속받고, Flyable 인터페이스를 구현합니다. 이 클래스는
sound()
메서드와eat()
메서드를 Animal 클래스에서 상속받고,fly()
메서드를 Flyable 인터페이스에서 구현합니다.클래스를 상속 받고, 인터페이스를 구현한 위와 같은 형태가 많이 사용됩니다. 상속은 반드시 추상 클래스일 필요는 없습니다.
Uploaded by N2T