JavaRush /Java Blog /Random-KO /커피 브레이크 #140. Java의 추상 클래스 및 인터페이스

커피 브레이크 #140. Java의 추상 클래스 및 인터페이스

Random-KO 그룹에 게시되었습니다
출처: InfoWorld 오늘은 개발자가 추상 클래스를 사용해야 하는 경우와 인터페이스를 사용해야 하는 경우에 대해 알아보겠습니다. 또한 Java 언어의 이러한 요소 간의 차이점과 이를 프로그램에서 사용하는 방법을 식별합니다. 커피 브레이크 #140.  Java의 추상 클래스 및 인터페이스 - 1추상 클래스와 인터페이스는 Java 코드는 물론 JDK(Java Development Kit) 자체에서도 매우 일반적입니다. 이러한 각 요소는 서로 다른 목적으로 사용됩니다.
  • 인터페이스는 추상 메소드와 정적 상수를 구현하는 데 도움이 되는 Java 언어의 구성입니다.
  • 추상 클래스는 추상 메서드, 즉 본문이 없는 메서드를 포함할 수 있다는 점을 제외하면 일반 클래스와 유사합니다. 추상 클래스를 만들 수 없습니다.
많은 개발자는 인터페이스와 추상 클래스가 유사하다고 생각하지만 실제로는 이것이 전적으로 사실이 아닙니다. 그들 사이의 주요 차이점을 살펴 보겠습니다.

인터페이스란 무엇입니까?

기본적으로 인터페이스는 계약이므로 생성 목적을 정의하는 구현에 따라 달라집니다. 인터페이스는 변경 가능한 인스턴스 변수를 사용할 수 없으며 최종 변수만 사용할 수 있습니다.

인터페이스를 사용하는 경우

인터페이스는 코드를 분리하고 다형성을 구현하는 데 매우 유용합니다. List 인터페이스를 사용하여 JDK에서 이를 확인할 수 있습니다 .
public interface List<E> extends Collection<E> {

    int size();
    boolean isEmpty();
    boolean add(E e);
    E remove(int index);
    void clear();
}
아마 눈치채셨겠지만 이 코드는 비록 간단하지만 상당히 설명적입니다. 구체적인 클래스를 사용하여 인터페이스에서 메서드를 구현하는 데 사용되는 메서드 시그니처를 쉽게 볼 수 있습니다. List 인터페이스에는 ArrayList , Vector , LinkedList 및 기타 클래스 에서 구현할 수 있는 계약이 포함되어 있습니다 . 다형성을 사용하려면 List를 사용하여 변수 유형을 선언한 다음 사용 가능한 인스턴스 중 하나를 선택하면 됩니다. 또 다른 예는 다음과 같습니다.
List list = new ArrayList();
System.out.println(list.getClass());

 List list = new LinkedList();
 System.out.println(list.getClass());
출력은 다음과 같습니다
클래스 java.util.ArrayList 클래스 java.util.LinkedList
이 경우 ArrayList , LinkedListVector 의 구현 방법이 다르며 이는 인터페이스를 사용하기 위한 훌륭한 시나리오입니다. 많은 클래스가 메서드 작업은 동일하지만 동작이 다른 상위 클래스에 속해 있는 경우. 이러한 상황에서는 인터페이스를 사용하는 것이 좋습니다. 다음으로 인터페이스 사용에 대한 몇 가지 옵션을 살펴보겠습니다.

인터페이스 메서드 재정의

이미 알고 있듯이 인터페이스는 구체적인 클래스에 의해 구현되어야 하는 일종의 계약입니다. 인터페이스 메서드 는 암시적으로 추상적이며 클래스의 구체적인 구현이 필요합니다. 예는 다음과 같습니다.
public class OverridingDemo {
  public static void main(String[] args) {
    Challenger challenger = new JavaChallenger();
    challenger.doChallenge();
  }
}

interface Challenger {
  void doChallenge();
}

class JavaChallenger implements Challenger {
  @Override
  public void doChallenge() {
    System.out.println("Challenge done!");
  }
}
결론:
도전 완료!
인터페이스 메소드는 암시 적으로 추상적입니다 . 즉, 명시적으로 abstract로 선언할 필요가 없습니다.

상수 변수

기억해야 할 또 다른 규칙은 인터페이스에는 상수 변수만 포함될 수 있다는 것입니다. 예는 다음과 같습니다.
public class Challenger {

  int number = 7;
  String name = "Java Challenger";

}
여기서 두 변수는 모두 암시적 finalstatic 입니다 . 즉, 인스턴스와 관계없이 일정하며 변경할 수 없습니다. 이제 Challenger 인터페이스 의 변수를 변경해 보겠습니다 . 예를 들어 다음과 같습니다.
Challenger.number = 8;
Challenger.name = "Another Challenger";
이로 인해 컴파일 오류가 발생합니다.
최종 변수 'number'에 값을 할당할 수 없습니다. 최종 변수 'name'에 값을 할당할 수 없습니다.

기본 방법

Java 8에 기본 메소드가 도입되었을 때 일부 개발자는 이것이 추상 클래스와 동일할 것이라고 생각했습니다. 그러나 인터페이스는 상태를 가질 수 없기 때문에 이는 사실이 아닙니다. 기본 메소드에는 구현이 있을 수 있지만 추상 메소드에는 구현이 없습니다. 기본 메서드는 람다 식과 스트림을 사용한 혁신의 결과이지만 신중하게 사용해야 합니다. 기본 메소드를 사용하는 JDK의 메소드는 Iterable 인터페이스 의 일부인 forEach() 입니다 . 각 Iterable 구현 에 코드를 복사하는 대신 forEach 메소드를 간단히 재사용할 수 있습니다 .
default void forEach(Consumer<? super T> action) {
  // Code implementation here...
모든 Iterable 구현은 새로운 메소드 구현 없이 forEach() 메소드를 사용할 수 있습니다 . 그런 다음 기본 메서드를 사용하여 코드를 재사용할 수 있습니다. 우리만의 기본 메소드를 만들어 보겠습니다:
public class DefaultMethodExample {

  public static void main(String[] args) {
    Challenger challenger = new JavaChallenger();
    challenger.doChallenge();
  }

}

class JavaChallenger implements Challenger { }

interface Challenger {

  default void doChallenge() {
    System.out.println("Challenger doing a challenge!");
  }
}
결과:
도전하는 챌린저!
기본 메서드와 관련하여 이러한 각 메서드를 구현해야 한다는 점에 유의하는 것이 중요합니다. 기본 메서드는 정적일 수 없습니다. 이제 추상 클래스로 넘어 갑시다.

추상 클래스의 본질

추상 클래스는 인스턴스 변수를 사용하여 상태를 가질 수 있습니다. 이는 인스턴스 변수를 사용하고 수정할 수 있음을 의미합니다. 예는 다음과 같습니다.
public abstract class AbstractClassMutation {

  private String name = "challenger";

  public static void main(String[] args) {
    AbstractClassMutation abstractClassMutation = new AbstractClassImpl();
    abstractClassMutation.name = "mutated challenger";
    System.out.println(abstractClassMutation.name);
  }

}

class AbstractClassImpl extends AbstractClassMutation { }
결론:
돌연변이 도전자

추상 클래스의 추상 메소드

인터페이스와 마찬가지로 추상 클래스에도 추상 메서드가 있을 수 있습니다. 추상 메서드는 본문이 없는 메서드입니다. 인터페이스와 달리 추상 클래스의 추상 메서드는 명시적으로 추상으로 선언되어야 합니다. 예는 다음과 같습니다.
public abstract class AbstractMethods {

  abstract void doSomething();

}
구현과 abstract 키워드 없이 메서드를 선언하려는 시도는 다음과 같습니다 .
public abstract class AbstractMethods {
   void doSomethingElse();
}
안타깝게도 다음과 같은 컴파일 오류가 발생합니다.
메소드 본문이 누락되었거나 추상을 선언했습니다.

추상 클래스를 사용해야 하는 경우

가변 상태를 구현해야 하는 경우 추상 클래스를 사용하는 것이 좋습니다. 예를 들어, Java 컬렉션 프레임워크에는 변수 상태를 사용하는 AbstractList 클래스가 포함되어 있습니다. 클래스 상태를 유지할 필요가 없는 경우 일반적으로 인터페이스를 사용하는 것이 더 좋습니다.

추상 클래스와 인터페이스의 차이점

객체 지향 프로그래밍 관점에서 인터페이스와 추상 클래스의 주요 차이점은 인터페이스는 상태를 가질 수 없는 반면 추상 클래스는 인스턴스 변수를 사용하여 상태를 가질 수 있다는 것입니다. 또 다른 주요 차이점은 클래스가 두 개 이상의 인터페이스를 구현할 수 있지만 추상 클래스는 하나만 확장할 수 있다는 것입니다. 이 솔루션은 다중 상속(둘 이상의 클래스 확장)으로 인해 코드 교착 상태가 발생할 수 있다는 사실을 기반으로 합니다. Java 언어 개발자는 이를 피하기로 결정했습니다. 또 다른 차이점은 인터페이스는 클래스로 구현되거나 인터페이스로 확장될 수 있지만 클래스는 확장만 가능하다는 것입니다. 람다 식은 기능적 인터페이스(메서드가 하나만 있는 인터페이스를 의미)에서만 사용할 수 있는 반면, 추상 메서드가 하나만 있는 추상 클래스는 람다 식을 사용할 수 없다는 점에 유의하는 것이 중요합니다. 추상 클래스와 인터페이스 간의 차이점은 다음과 같습니다. 상호 작용:
  • 최종 정적 변수만 가질 수 있습니다. 인터페이스는 자신의 상태를 변경할 수 없습니다.
  • 클래스는 여러 인터페이스를 구현할 수 있습니다.
  • Implements 키워드를 사용하여 구현할 수 있습니다. 인터페이스는 다른 인터페이스를 확장할 수 있습니다.
  • 메서드는 정적 최종 필드, 매개변수 또는 지역 변수만 사용할 수 있습니다.
  • 기능적 인터페이스만 Java에서 람다 함수를 사용할 수 있습니다.
  • 생성자를 가질 수 없습니다.
  • 추상 메서드가 있을 수 있습니다.
  • 기본 및 정적 메소드를 가질 수 있습니다(Java 8에서 도입됨).
  • 구현을 통해 개인 메소드를 가질 수 있습니다(Java 9에서 도입됨).
추상 클래스:
  • 변경 가능하거나 변경 불가능한 모든 인스턴스 또는 정적 변수를 가질 수 있습니다.
  • 클래스는 하나의 추상 클래스만 확장할 수 있습니다.
  • 변경 가능한 필드, 매개변수 또는 지역 변수의 인스턴스가 있을 수 있습니다.
  • 하나의 추상 메서드만 있는 추상 클래스는 람다 식을 사용할 수 없습니다.
  • 생성자가 있을 수 있습니다.
  • 어떤 메소드든 가질 수 있습니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION