programing

사용 시기: Java 8+ 인터페이스 기본 방식과 추상 방식 비교

goodsources 2022. 7. 26. 23:44
반응형

사용 시기: Java 8+ 인터페이스 기본 방식과 추상 방식 비교

Java 8에서는 Default Methods라고 불리는 인터페이스에서 메서드를 기본 구현할 수 있습니다.

언제 그런 걸 써야 할지 모르겠어요.interface default method의 대신,abstract class(와 함께)abstract method(s)).

기본 메서드와의 인터페이스는 언제 사용해야 하며 추상 클래스(추상 메서드 포함)는 언제 사용해야 합니까?추상 클래스는 그 시나리오에서 여전히 유용합니까?

기본 메서드 구현(프라이빗 상태 등)보다 추상 클래스가 훨씬 더 많지만 Java 8부터는 어느 하나를 선택할 수 있을 때마다 Defender(일명 Defender)를 사용해야 합니다.default) 메서드를 지정합니다.

디폴트 메서드의 제약사항은 특정 구현 상태를 참조하지 않고 다른 인터페이스 메서드에 대한 호출에서만 구현할 수 있다는 것입니다.따라서 주요 사용 사례는 보다 높은 수준의 편리한 방법입니다.

이 새로운 기능의 좋은 점은 편의 메서드에 추상 클래스를 사용해야만 했기 때문에 구현자가 단일 상속으로 제한되었던 것이 이제는 인터페이스와 프로그래머에게 강요된 최소한의 구현 노력으로 매우 깨끗한 설계를 할 수 있다는 것입니다.

도입의 원래 동기defaultJava 8로의 메서드는 기존 구현을 중단하지 않고 람다 지향 메서드로 컬렉션 프레임워크 인터페이스를 확장하고자 하는 욕구였다.이 기능은 공공도서관 작성자와 더 관련이 있지만 프로젝트에서도 도움이 될 수 있습니다.새로운 편의성을 추가할 수 있는 중앙 집중식 장소가 하나 있어 나머지 유형의 계층 구조에 의존할 필요가 없습니다.

기술적인 차이가 몇 가지 있습니다.추상 클래스는 Java 8 인터페이스에 비해 더 많은 작업을 수행할 수 있습니다.

  1. 추상 클래스에는 생성자가 있을 수 있습니다.
  2. 추상 클래스는 보다 체계적이고 상태를 유지할 수 있습니다.

개념적으로 Defender 메서드의 주요 목적은 Java 8에서 새로운 기능(람다 함수)이 도입된 후 하위 호환성이라는 것입니다.

이것은 기사에서 설명하고 있습니다.대해 생각하다forEach의 컬렉션입니다.

List<?> list = …
list.forEach(…);

forEach는 다음 항목에 의해 선언되지 않습니다.java.util.List또한java.util.Collection아직 인터페이스가 없습니다.한 가지 확실한 해결책은 기존 인터페이스에 새로운 방법을 추가하고 필요에 따라 JDK에서 구현을 제공하는 것입니다.단, 퍼블리시된 후에는 기존 구현을 중단하지 않고 인터페이스에 메서드를 추가할 수 없습니다.

디폴트 메서드가 가져오는 이점은 새로운 디폴트메서드를 인터페이스에 추가할 수 있게 되어 구현을 중단하지 않는다는 것입니다.

기사에서 설명한 바와 같이

Java 8의 추상 클래스와 인터페이스 비교

Default Method를 도입한 후 인터페이스와 추상 클래스는 동일한 것으로 보입니다.그러나 Java 8에서는 여전히 다른 개념입니다.

추상 클래스는 생성자를 정의할 수 있습니다.이들은 보다 구조화되어 있으며 이와 관련된 상태를 가질 수 있습니다.반면 디폴트 메서드는 특정 구현 상태를 참조하지 않고 다른 인터페이스 메서드를 호출하는 관점에서만 구현할 수 있습니다.따라서 둘 다 다른 목적으로 사용하며 둘 중 하나를 선택하는 것은 시나리오 상황에 따라 다릅니다.

추상 클래스와 인터페이스 중에서 선택할 수 있는 경우에는 항상 디폴트(defender 또는 가상 확장이라고도 함) 방식을 선호해야 합니다.

  1. 디폴트 메서드에서는 인터페이스의 클래식패턴과 그 인터페이스에 대부분의 메서드 또는 모든 메서드를 구현하는 컴패니언 클래스가 종료되었습니다.예를 들면,Collection and AbstractCollection이제 기본 기능을 제공하기 위해 인터페이스 자체에 메서드를 구현해야 합니다.인터페이스를 구현하는 클래스는 메서드를 덮어쓰거나 기본 구현을 상속할 수 있습니다.

  2. 기본 방식의 또 다른 중요한 용도는 다음과 같습니다.interface evolution다음과 같은 클래스 볼이 있다고 가정합니다.

    public class Ball implements Collection { ... }

Java 8에서는 새로운 기능 스트림이 도입되었습니다.스트림을 얻으려면stream메서드가 인터페이스에 추가되었습니다.한다면stream모든 구현이 기본 방식은 아니었습니다.Collection이 새로운 메서드를 구현하지 않기 때문에 인터페이스가 파손되었을 것입니다.인터페이스에 디폴트 이외의 메서드를 추가하는 것은source-compatible.

그러나 클래스를 다시 컴파일하지 않고 이 클래스를 포함하는 오래된 jar 파일을 사용한다고 가정합니다.Ball이 메서드가 없으면 클래스는 정상적으로 로딩됩니다.인스턴스를 생성할 수 있고 모든 것이 정상적으로 동작하고 있는 것 같습니다.그러나 프로그램이 호출하는 경우streamBall는 것이다.AbstractMethodError따라서 메서드를 디폴트로 하면 두 가지 문제가 모두 해결됩니다.

Java 9에는 기본 구현을 제공한 인터페이스 메서드에서 사용된 공통 코드 로직을 캡슐화하기 위해 사용할 수 있는 개인 메서드가 있습니다.

이 두 가지는 상당히 다릅니다.

기본 메서드는 상태를 변경하지 않고 기존 클래스에 외부 기능을 추가하는 것입니다.

추상 클래스는 일반 상속 유형으로 확장되는 일반 클래스입니다.

비록 오래된 질문이지만, 그것에 대한 제 의견도 드리겠습니다.

  1. 추상 클래스:추상 클래스 내에서 자식 클래스에 필요한 인스턴스 변수를 선언할 수 있습니다.

    인터페이스:내부 인터페이스에서는 모든 변수가 항상 퍼블릭 스태틱이며 최종적으로 인스턴스 변수를 선언할 수 없습니다.

  2. 추상 클래스:추상 클래스는 객체의 상태에 대해 이야기할 수 있습니다.

    인터페이스:인터페이스는 오브젝트 상태를 말할 수 없습니다.

  3. 추상 클래스:Abstract 클래스 내에서 생성자를 선언할 수 있습니다.

    인터페이스:내부 인터페이스에서는 컨스트럭터를 목적으로 선언할 수 없습니다.
    생성자는 인스턴스 변수를 초기화합니다. 인터페이스에 인스턴스 변수를 포함할 수 없는 경우 컨스트럭터가 필요한 것은 무엇입니까?

  4. 추상 클래스:추상 클래스 내에서 인스턴스 및 정적 블록을 선언할 수 있습니다.

    인터페이스:인터페이스에는 인스턴스와 스태틱블록을 사용할 수 없습니다.

  5. 추상 클래스:추상 클래스는 람다 식을 참조할 수 없습니다.

    인터페이스:단일 추상 메서드를 사용하는 인터페이스는 람다 식을 참조할 수 있습니다.

  6. 추상 클래스:추상 클래스 내에서 OBJECT CLASS 메서드를 재정의할 수 있습니다.

    인터페이스:인터페이스 내부의 OBJECT CLASS 메서드는 덮어쓸 수 없습니다.

마지막으로 다음과 같이 하겠습니다.

인터페이스의 디폴트 메서드 개념/스태틱 메서드 개념은 구현 클래스를 저장하기 위한 것일 뿐 의미 있는 구현을 제공하기 위한 것은 아닙니다.디폴트 메서드/스태틱메서드는 '실장 클래스에서 사용할 수 있는 경우 또는 (디폴트메서드의 경우) 덮어쓸 수 있는' 일종의 더미 구현입니다.따라서 인터페이스에 새로운 메서드가 추가될 때마다 구현 클래스에서 새로운 메서드를 구현할 필요가 없습니다.따라서 인터페이스는 추상 클래스와 같을 수 없습니다.

문의하신 내용에 대해서

기본 메서드와의 인터페이스는 언제 사용해야 하며 추상 클래스는 언제 사용해야 합니까?추상 클래스는 그 시나리오에서 여전히 유용합니까?

Java 문서는 완벽한 답을 제공합니다.

인터페이스와 비교한 추상 클래스:

추상 클래스는 인터페이스와 비슷합니다.인스턴스화할 수 없으며 구현 여부에 관계없이 선언된 메서드가 혼재되어 있을 수 있습니다.

그러나 추상 클래스를 사용하면 정적 및 최종 필드가 아닌 필드를 선언하고 공개, 보호 및 개인 방법을 정의할 수 있습니다.

인터페이스에서는 모든 필드가 자동으로 public, static 및 final이 되며 선언 또는 정의한 모든 방식(기본 방식)이 public이 됩니다.또한 추상인지 여부에 관계없이 확장할 수 있는 클래스는 1개뿐이지만, 구현 가능한 인터페이스의 수는 임의입니다.

각각의 사용 사례에 대해서는, 이하의 SE 포스트에 설명되어 있습니다.

인터페이스와 추상 클래스의 차이점은 무엇입니까?

추상 클래스는 그 시나리오에서 여전히 유용합니까?

네, 아직 쓸만해요.비정적, 비최종적인 메서드 및 속성(public 외에 보호, 프라이빗)을 포함할 수 있습니다.이는 Java-8 인터페이스에서도 불가능합니다.

Java 인터페이스의 디폴트 방식에서는, 인터페이스의 진화를 netable로 합니다.

기존 인터페이스를 지정하면 인터페이스의 이전 버전과의 바이너리 호환성을 해치지 않고 메서드를 추가할 경우 디폴트메서드와 스태틱메서드의 2가지 옵션이 준비되어 있습니다.실제로 인터페이스에 추가된 추상 메서드는 이 인터페이스를 구현하는 클래스 또는 인터페이스에 의해 삭제되어야 합니다.

스태틱 메서드는 클래스에 고유합니다.기본 메서드는 클래스의 인스턴스에 고유합니다.

디폴트 메서드를 기존 인터페이스에 추가하면 이 인터페이스를 구현하는 클래스 및 인터페이스에서는 구현할 필요가 없습니다.그들은 할 수 있다

  • 디폴트 방식을 실장하고, 실장 인터페이스에서의 실장을 덮어씁니다.
  • (실장하지 않고) 메서드를 재실행함으로써 추상화한다.
  • 아무것도 하지 않습니다(실장된 인터페이스로부터의 디폴트 방식은 단순히 상속됩니다).

자세한 내용은 이쪽.

Remi Forax 규칙은 추상 클래스로 설계하지 않습니다. 인터페이스를 사용하여 앱을 디자인합니다.wistern은 자바 버전입니다.언어가 무엇이든 상관없습니다.SOLID 원칙의 인터페이스 분리 원칙에 의해 지원됩니다.

나중에 추상 클래스를 사용하여 코드를 인수분해할 수 있습니다.Java 8에서는 인터페이스에서 직접 실행할 수 있습니다.이건 시설이지 그 이상은 아니야

기본 메서드와의 인터페이스는 언제 사용해야 하며 추상 클래스는 언제 사용해야 합니까?

하위 호환성:인터페이스가 수백 개의 클래스로 구현되어 있다고 가정해 봅시다.이 인터페이스를 변경하면 모든 사용자가 새로 추가된 메서드를 구현해야 합니다.단, 인터페이스를 구현하는 다른 클래스에는 필수적이지 않을 수 있습니다.또한 인터페이스를 기능적인 인터페이스로 만들 수 있습니다.

정보 및 제약사항:

1-클래스 또는 추상 클래스 내에서가 아닌 인터페이스 내에서만 선언할 수 있습니다.

2-본문을 제공해야 합니다.

3-인터페이스에서 사용되는 다른 일반 방법과는 달리 추상적이라고 가정하지 않습니다.

Java 8에서는 인터페이스는 추상 클래스와 비슷하지만 다음과 같은 차이가 있을 수 있습니다.

1) 추상 클래스는 클래스이므로 Java의 인터페이스의 다른 제한에 제한되지 않습니다.예를 들어 추상 클래스는 상태를 가질있지만 Java의 인터페이스 상태는 가질 수 없습니다.

2) 기본 메서드를 사용하는 인터페이스와 추상 클래스의 또 다른 의미적 차이는 추상 클래스 내에서는 컨스트럭터를 정의할 수 있지만 Java에서는 컨스트럭터 내부 인터페이스를 정의할 수 없다는 입니다.

Java Interface의 기본 메서드는 함수의 더미 구현을 제공하기 위해 더 많이 사용되며, 따라서 해당 인터페이스의 구현 클래스는 하나만 처리하려고 해도 모든 추상 메서드를 선언해야 하는 번거로움에서 벗어나게 됩니다.따라서 인터페이스의 디폴트 메서드는 어댑터 클래스의 개념을 대체하는 것에 가깝습니다.

그러나 추상 클래스의 메서드는 공통 기능을 재정의해야 하는 경우에만 하위 클래스가 재정의해야 하는 의미 있는 구현을 제공해야 합니다.

다른 답변에서 설명한 바와 같이 Collections 프레임워크에서 하위 호환성을 제공하기 위해 인터페이스에 구현을 추가하는 기능이 추가되었습니다.하위 호환성을 제공하는 것이 인터페이스에 구현을 추가하는 유일한 타당한 이유일 수 있습니다.

그 이외의 경우, 인터페이스에 실장을 추가하면, 최초로 인터페이스가 추가된 이유에 관한 기본 법칙이 위반됩니다.Java는 여러 상속을 허용하는 C++와는 달리 단일 상속 언어입니다.인터페이스는 여러 상속에서 발생하는 문제를 발생시키지 않고 여러 상속을 지원하는 언어와 함께 제공되는 입력상의 이점을 제공합니다.

구체적으로는 Java는 구현의 단일 상속만 허용하지만 인터페이스를 여러 번 상속할 수 있습니다.예를 들어, 다음은 유효한 Java 코드입니다.

class MyObject extends String implements Runnable, Comparable { ... }

MyObject는 1개의 구현만 상속하지만 3개의 계약을 상속합니다.

Java는 구현의 여러 상속을 전달했습니다. 왜냐하면 구현의 여러 상속은 이 답변의 범위를 벗어나는 까다로운 문제를 수반하기 때문입니다.구현의 다중 상속 문제 없이 계약(인터페이스라고도 함)을 여러 번 상속할 수 있도록 인터페이스가 추가되었습니다.

제 요점을 뒷받침하기 위해, Ken Arnold와 James Gosling이 Java Programming Language, 제4판에서 인용한 을 소개합니다.

단일 상속으로는 일부 유용하고 정확한 설계를 할 수 없습니다.다중 상속의 문제는 구현의 다중 상속에서 발생하지만, 많은 경우 다수의 추상적 계약과 아마도 하나의 구체적인 구현을 상속하기 위해 다중 상속이 사용됩니다.구현을 상속하지 않고 추상 계약을 상속하는 수단을 제공하면 여러 구현 상속의 문제 없이 여러 상속의 타이핑 이점을 얻을 수 있습니다.추상계약의 상속을 인터페이스 상속이라고 합니다.Java 프로그래밍 언어는 인터페이스 상속을 지원합니다.interface

비즈니스 유스케이스 컨텍스트에서 인터페이스를 사용하여 특정 비즈니스 규칙을 정의할 수 있습니다.이 경우 추상 클래스는 비즈니스를 시작하기 위한 공통 구조를 정의합니다.

및 Walmart와 하면, 서 정의되고 있는 는, 「Amazon 및 Walmart」라고 것이 .WalmartPartner ★★★★★★★★★★★★★★★★★」AmazonPartner 클래스를 합니다.BusinessSetup는 특정 지역의 비즈니스 셋업을 가져옵니다.

// Interfaces
 
public interface WalmartPartner {
    public static boolean signUpForWalmartBusinessAccount(String BusinessId){
        System.out.println("Setting up Walmart Business Partner");
        return true;
    }
    public default  void  getWalmartDeals(){
        System.out.println("Default walmart deal executed !");
    }
    public abstract void setupShopifyForWalmart();
    public abstract  void setupWalmartProducts();

public interface AmazonPartner {
    public static boolean signUpAsAmazonServicePartner(String BusinessId){
        System.out.println("Setting up Amazon Business Partner");
        return true;
    }
    public default  void  paymentPlatformSetup(){
        System.out.println(" Amazon default payment platform is setup");
    }
    public abstract void setupPrimeMemberDealsByRegion();
    public abstract  void setupPrimeDeals();
}

 // Abstract class 

public abstract class BusinessSetup {
    String businessId ;
    public BusinessSetup(String businessId){
        this.businessId = businessId;
        System.out.println("1. Initial Business setup for BusienssID: "+this.businessId+" is Complete");
    }
    public final boolean getBusinessRegisteredInRegion(String region){
        System.out.println("2. Business got registered in "+region+ "!");
        return true;
    }
    public abstract void setupCustomerPlatform(String customerId);
    public abstract void setupVendorPlatform(String vendorId);

}

// Concrete Class 
public class WalMartPartnerImpl extends BusinessSetup implements WalmartPartner {
    public WalMartPartnerImpl(String businessId) {
        super(businessId);
    }
    @Override
    public void setupCustomerPlatform(String customerId) {
    }

    @Override
    public void setupVendorPlatform(String vendorId) {
    }

    @Override
    public void setupShopifyForWalmart() {
    }

    @Override
    public void setupWalmartProducts() {
    }
    public static void main(String args[]){
        WalMartPartnerImpl walMartPartner = new WalMartPartnerImpl("wal8989");
        walMartPartner.getBusinessRegisteredInRegion("california");
        walMartPartner.getWalmartDeals();
        walMartPartner.setupCustomerPlatform("wal8989");

    }
}

우선 열린/닫힌 원칙을 생각해 주세요.인터페이스의 디폴트 메서드는 이를 위반합니다.이것은 Java에서 나쁜 기능입니다.설계 불량, 아키텍처 불량, 소프트웨어 품질 저하를 부추깁니다.기본 방식을 완전히 사용하지 않는 것이 좋습니다.

자신에게 몇 가지 질문을 합니다.왜 당신의 방법을 추상 수업에 넣을 수 없나요?그럼 추상 수업이 하나 이상 필요하신가요?그러면 여러분의 학급이 무엇을 책임지고 있는지 생각해 보세요.단일 클래스에 적용할 모든 방법이 실제로 동일한 목적을 달성한다고 확신하십니까?여러 가지 목적을 구별하고 각 목적에 따라 클래스를 여러 클래스로 분할할 수 있습니다.

언급URL : https://stackoverflow.com/questions/19998454/when-to-use-java-8-interface-default-method-vs-abstract-method

반응형