들어가며
이번 포스트에서는 Interface에 대하여 정리합니다.
Interface?
기존의 인터페이스가 가르키는 말은 다음과 같습니다.
서로 다른 두 개의 시스템, 장치 사이에서 정보나 신호를 주고받는 경우의 접점이나 경계면
즉, 사용자가 기기를 쉽게 동작 시키는데 도움을 주는 시스템을 의미합니다.
이런 화면들도 인터페이스 화면입니다.
Java에서 Interface
클래스가 가져야 하는 메서드의 명세(specification)를 정의합니다.
즉, 인터페이스는 어떤 클래스가 특정한 메서드를 반드시 구현해야 한다는 것을 보장합니다. 인터페이스는 클래스가 아닌, 구현되지 않은 메서드의 집합을 나타냅니다.
// 동물의 소리를 나타내는 인터페이스
interface Animal {
void makeSound();
}
// 각각의 동물 클래스들이 해당 인터페이스를 구현
class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("멍멍");
}
}
class Cat implements Animal {
@Override
public void makeSound() {
System.out.println("야옹");
}
}
class Cow implements Animal {
@Override
public void makeSound() {
System.out.println("음메");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
Animal cow = new Cow();
dog.makeSound(); // 멍멍
cat.makeSound(); // 야옹
cow.makeSound(); // 음메
}
}
예시 코드처럼 인터페이스로 선언하고 내부에 메서드는 구현되지 않은 상태입니다.
이전 추상메서드 포스트에서 이야기 한 것과 동일합니다.
즉, 인터페이스는 추상메서드를 통해서만 구현이 가능하다는 것을 말합니다.
특징이 여러가지 있는데
- 상수 정의 : 자바에서 상수를 정의할 때는 public static final을 붙여 정의합니다.
- 자동으로 선언하여 관리됩니다.
- 다중상속 = 다형성을 구현할 수 있습니다. - implements
- 객체의 역할을 지정합니다. 따라서 특정 객체가 어떤 행위를 해야하는지를 정의 해둘 수 있습니다.
이렇게 인터페이스를 쓰게 되면 하나의 메서드의 종속되는 결합도를 줄일 수 있습니다.
따라서 재사용성이 높아지고 , 코드의 효율성이 높아집니다.
implements?
implements란 구현하다. implement는 도구 라는 의미입니다.
추상 클래스에서 추상 메서드를 통해 명세한 - 선언한 메서드를
implements - 구현하겠다 라는 의미로 생각됩니다.
자바에서 상속을 구현하는 두가지 방법중 하나입니다.
다중 상속을 구현할 수 있는 방법인데
사실 자바에서는 다중 상속을 지원하지 않습니다.
? 방금 지원한다매
다중 상속을 java가 금지한 이유
그 이유는 여러가지 있지만 가장 대표적으로
다이아몬드 문제 방지
다중 상속을 허용하면 다이아몬드 문제가 발생할 수 있습니다.
이는 하위 클래스가 여러 상위 클래스로부터 상속 받을 때, 상위 클래스 간의 충돌이 발생할 수 있는 문제입니다. 이로 인해 코드의 복잡성이 증가하고, 가독성이 떨어지며 디버깅이 어려워집니다.
즉, 여러개의 클래스를 상속 받으면 충돌이 발생하였을 때 어디서 문제가 발생하였는지 찾기 힘들어집니다.
그래서 Spring을 사용할 때
시험 문제였던걸로 기억합니다.
1번 클래스 , 2번 클래스의 상속을 받아 3번 클래스를 구현 해야 하는 일이 있었습니다.
그래서 저는 2번을 1번으로 부터 자식 클래스로 두고 다시 2번 클래스를 3번 클래스의 부모로 만들어 해결했던 경험이 있습니다.
코드가 돌아가서 맞은 걸로 채점이 되었던 것 같은데
지금 공부해보며 생각이든게 인터페이스를 구현해서 문제를 해결하라는 의도였던 것 같습니다.
어쨌든 다이아몬드 문제방지 이외에도
- 명확성과 복잡성: 다중 상속은 클래스 간의 관계를 복잡하게 만들 수 있습니다. 특히 다중 상속을 사용할 때 클래스의 메서드 충돌을 해결하는 방법이 명확하지 않을 수 있습니다. 이는 코드의 이해와 유지보수를 어렵게 만듭니다.
- 디자인의 목적: Java의 설계 목표 중 하나는 간결하고 명확한 객체 지향 디자인을 제공하는 것입니다. 다중 상속은 이 목표를 방해할 수 있습니다. 대신 인터페이스와 추상 클래스를 통해 다중 상속과 유사한 기능을 제공하면서도 이러한 문제를 방지할 수 있습니다.
- 자바의 단순성: Java는 간결하고 단순한 언어로 유명합니다. 다중 상속을 지원하면 언어의 복잡성이 증가할 수 있으며, 개발자들이 언어를 이해하고 사용하는 데 어려움을 겪을 수 있습니다.
위와 같은 이유로 다중 상속을 지원하지 않습니다.
public interface PaymentProcessor {
void processPayment();
}
public class CreditCardProcessor implements PaymentProcessor {
@Override
public void processPayment() {
// 신용카드 결제 처리하는 로직
}
}
이런식으로 사용하는데
extends 와 가장 큰 차이점은 @Override 즉, 오버라이딩에 대한 명시를 해야 하느냐의 차이입니다.
아래 포스트의 관련 내용을 정리해 놨습니다.
중요한 것은 그럼 exteds는 @Override 안쓰냐 - 아니요 씁니다.
이전 포스트에서도 말하였지만 해당 어노테이션은 자바 컴파일러에게 여기 상속받아요
라고 알려주는 겁니다.
없어도 알아서 찾아보지만 명시해두면 문제가 생길 가능성을 먼저 제거합니다.
따라서 사용을 하는 것이 좋지만 exteds는 @Override를 안쓴다고 컴파일러가 오류로 처리하지 않는다는 의미입니다.
왜 오류로 안잡냐
클래스가 다른 클래스를 확장할 때, 해당 클래스가 이미 컴파일된 바이트 코드에 포함되어 있기 때문입니다.
따라서 컴파일러는 자식 클래스가 부모 클래스의 메서드를 오버라이드하고 있는지를 정확히 알 수 있습니다.
즉, 부모 클래스에서 이미 정의를 한 내용을 자식 클래스에서 그대로 받아 쓸 수 도 있기 때문입니다.
즉, extends는 class - class 간의 상속을 정의하고 자바에서는 기본적으로 class간의 상속은 1회로 규정하는 것입니다.
그런데 interface는 추상 메서드를 선언하고 implements로 선언된 실제 클래스에서 구현됩니다.
이전 포스트에서 추상클래스의 메서드인 추상 메서드는 전부 구현하지 않고 불안정한 상태에서 구현을 상속받은 클래스에서 구현한다고 이야기 하였습니다.
이런이유로 implements의 경우 반드시 @Overrid를 붙여야 컴파일러가 알 수 있기 때문에
오류를 발생 시키는 것 입니다.
다중 상속의 구현 implements
즉, 다중 상속은 안됩니다. - 그런데 implements를 통해서 라면
유사하게 기능을 구현할 수 있습니다.
// 인터페이스 1
interface Animal {
void sound();
}
// 인터페이스 2
interface Movable {
void move();
}
// Animal과 Movable 인터페이스를 모두 구현하는 클래스
class Dog implements Animal, Movable {
@Override
public void sound() {
System.out.println("멍멍");
}
@Override
public void move() {
System.out.println("걷기");
}
}
// 사용 예시
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound(); // 멍멍
dog.move(); // 걷기
}
}
이런 방법으로 구현해 볼 수 있습니다.
이것이 왜 필요하냐면 만약 extends만 사용해? 구현하려면
class가 더 많이 필요하고 , 더 많은 쓸데없이 선언하는 코드가 증가하게 되고 서로 간의 종속이 생기게 됩니다.
당연히 코드 읽기 복잡해지고, 유지 보수가 어려워 진다는 점이 생깁니다.
따라서 해당 방법을 통해 특정 메서드를 복수개 처리할 때 사용해 볼 수 있습니다.
개인적인 생각
근데 구현한다 는 의미가 상속과 같은 선상에서의 의미인지는 잘 모르겠습니다.
상속한다는 것은 받아와서 사용한다는 의미이고, 이것을 그대로 사용하던 바꿔서 사용하던의 문제인데
구현한다는 것은 말 그대로 구현하는 건데 음.. 관련된 정보를 보게 되면 공유하겠습니다!
정리하며
이번 포스트에서는 interface에 대해 이야기 해봤습니다.
interface는 추상메서드를 선언하고 이런 추상메서드는 implements를 통해 구현한다.
implements를 사용하면 다중 상속과 유사한 기능을 구현할 수 있고,
extends와의 차이점에 대해서도 이야기 해봤습니다.
사실 implements vs extends는 정말 자료가 많습니다.
'JAVA' 카테고리의 다른 글
JAVA-어노테이션에 대하여 (0) | 2024.06.03 |
---|---|
JAVA - 결합도에 대하여 (0) | 2024.06.03 |
JAVA - OOP 실사용 (0) | 2024.05.29 |
JAVA-OverLoding & OverRiding (0) | 2024.05.29 |
JAVA-스레드 (0) | 2024.05.28 |