Interface와 Abstract 클래스의 차이점을 어떻게 설명해야합니까?


469

인터뷰 중 하나에서 인터페이스추상 클래스 의 차이점을 설명하라는 요청을 받았습니다 .

내 대답은 다음과 같습니다.

Java 인터페이스의 메소드는 내재적으로 추상적이며 구현할 수 없습니다. Java 추상 클래스에는 기본 동작을 구현하는 인스턴스 메소드가있을 수 있습니다.

Java 인터페이스에서 선언 된 변수는 기본적으로 final입니다. 추상 클래스에는 비 최종 변수가 포함될 수 있습니다.

Java 인터페이스의 멤버는 기본적으로 공용입니다. Java 추상 클래스는 개인, 보호 등의 일반적인 클래스 멤버를 가질 수 있습니다.

Java 인터페이스는 키워드 "implements"를 사용하여 구현해야합니다. 키워드“extends”를 사용하여 Java 추상 클래스를 확장해야합니다.

인터페이스는 다른 Java 인터페이스 만 확장 할 수 있으며 추상 클래스는 다른 Java 클래스를 확장하고 여러 Java 인터페이스를 구현할 수 있습니다.

Java 클래스는 여러 인터페이스를 구현할 수 있지만 하나의 추상 클래스 만 확장 할 수 있습니다.

그러나 면접관은 만족하지 않았으며,이 설명은 " 서적 지식 "을 대표한다고 말했다 .

그는 실용적인 예제를 사용하여 인터페이스를 통해 추상 클래스를 선택할 때를 설명하는보다 실용적인 응답을 요청했습니다 .

내가 어디로 잘못 갔니?


32
어쩌면 당신이 이해하지 못하는 것을 말하고있는 것처럼 보였을까요? 자신의 말처럼 보이도록 말하는 스타일을 변경하기 만하면됩니다.
Kirill Kobelev

19
당신은 (아주 정확한) 기술적 차이점의 목록으로 대답했습니다. 면접관은보다 개념적 답변을 찾고있을 가능성이 높았다 (예를 들어, 인터페이스와 추상 클래스를 사용하여 어떤 기준을 선택할 것인가).
Ted Hopp

15
추상 클래스 인 const를 인스턴스화 할 수는 없지만 추상 클래스에는 생성자가 있다고 말하는 것을 잊었습니다. 자식 클래스에서 사용됩니다. 인터페이스는 부재 중 계약 (메소드 목록)을 정의하기 때문에 "무엇"을 나타내지 만 "어떻게"를 나타내지 않습니다. 클래스는 "방법"(메소드 구현)을 나타낼 수도 있습니다. int 사용 다중 상속을 에뮬레이션 할 수 있습니다 (클래스는 여러 개의 int를 구현할 수 있지만 하나의 클래스 만 확장 할 수 있습니다). int 사용 dif의 기본 유형을 가질 수 있습니다. 가족 : 전단지 f = new Plane (); Flyer f2 = new Bird (); 새와 비행기는 같은 가족과 일치하지 않지만 둘 다 날 수 있습니다 (전단지).
Francisco Goldenstein

7
java8 인터페이스에서 메소드를 포함 할 수 있습니다. OO 개념을 넘어서서 이러한 "차이점"은 하루 하루 변경 될 수 있습니다.
링 베어러

15
나는 당신의 대답에 아무런 문제가 없으며, 면접관이 '서적 지식'에 대해 조롱 할 사업이 없다고 생각합니다. 면접관은 항상 자신이 묻는 질문에 대한 정답을 알지 못하며 일부 면담은 그 곳에서 일하지 말라고 경고하는 역할 만합니다.
Lorne의 후작

답변:


513

먼저 예를 들어 보겠습니다.

public interface LoginAuth{
   public String encryptPassword(String pass);
   public void checkDBforUser();
}

응용 프로그램에 3 개의 데이터베이스가 있다고 가정하십시오. 그런 다음 해당 데이터베이스에 대한 모든 구현마다 위의 두 가지 방법을 정의해야합니다.

public class DBMySQL implements LoginAuth{
          // Needs to implement both methods
}
public class DBOracle implements LoginAuth{
          // Needs to implement both methods
}
public class DBAbc implements LoginAuth{
          // Needs to implement both methods
}

그러나 encryptPassword()데이터베이스에 의존하지 않고 각 클래스마다 동일한 경우 어떻게해야합니까? 그렇다면 위의 방법은 좋지 않습니다.

대신이 접근법을 고려하십시오.

public abstract class LoginAuth{
   public String encryptPassword(String pass){
            // Implement the same default behavior here 
            // that is shared by all subclasses.
   }

   // Each subclass needs to provide their own implementation of this only:
   public abstract void checkDBforUser();
}

이제 각 자식 클래스에서 데이터베이스에 의존하는 메서드 하나만 구현하면됩니다.


97
이것이 실제로 차이점을 설명하는지 잘 모르겠습니다 ... 좋은 기술인지 확인하십시오. Java 8이 마침내 C ++이 옳았으며 다중 상속이 가능하고 사용할 수 있으며 인터페이스가 함수 서명뿐만 아니라 기본 구현을 정의 할 수 있음을 인정한 것으로 생각합니다. 따라서 인터페이스를 사용하는 것이 좋습니다.
thecoshman

1
@ thecoshman 대답 (한 메소드가 구현 된 추상 클래스와 다른 초록이있는 추상 클래스)에서 문제에 접근하거나 기본 메소드 구현으로 인터페이스를 정의하면 어떤 차이가 있습니까? 기본적으로, 내가 말하려는 것은 '인터페이스를 사용하는 것이 바람직 할 것'이라고 썼는데 내 질문은-왜?
Neutrino

1
따라서 인터페이스를 사용하여 정의 된 내용의 구현은 실제로 인터페이스를 구현하는 클래스에 달려 있지만 추상 클래스의 항목은 클래스를 확장하는 클래스의 "핵심"이라고 말할 수 있습니다. 즉, 변경되지 않습니다.
orrymr

4
@Neutrino Java가 각 기능에 대한 기본 구현을 제공하는 여러 인터페이스를 구현할 수 있지만 여전히 단일 클래스 만 확장 할 수 있습니다. 따라서 인터페이스를 사용하면 다른 인터페이스와 함께 인터페이스를 사용하려는 사람들에게 더 많은 유연성을 제공 할 수 있습니다.
thecoshman

3
@HiradNikoo 늦은 의견에 대해 죄송하지만 방금이 스레드에서 우연히 발견되었습니다. 클래스 상속을 IS-A 관계로 간주 할 수 있지만 인터페이스는 "특정 기능이 있음"을 나타냅니다.
Alexander Jank

206

이 세상에서 완벽한 것은 없습니다. 그들은 실제적인 접근 방식을 기대했을 수도 있습니다.

그러나 설명 후에 약간 다른 접근 방식 으로이 줄을 추가 할 수 있습니다.

  1. 인터페이스는 소프트웨어 개발의 여러 팀에서 공통으로 이해하는 문서로 작동하는 규칙 (규칙을 무시하거나 피할 수없는 구현을 제공해야하기 때문에 적용되는 규칙)입니다.

  2. 인터페이스는 수행해야 할 작업에 대한 아이디어를 제공하지만 수행 방법은 제공하지 않습니다. 따라서 구현은 주어진 규칙에 따라 개발자에게 전적으로 달려 있습니다 (메소드의 서명이 주어진다는 것을 의미합니다).

  3. 추상 클래스에는 추상 선언, 구체적 구현 또는 둘 다가 포함될 수 있습니다.

  4. 추상 선언은 준수해야 할 규칙과 같으며 구체적인 구현은 지침과 같습니다 (그대로 그대로 사용하거나 구현을 재정의하고이를 통해 무시할 수 있음).

  5. 또한 동일한 서명을 가진 메소드가 다른 컨텍스트에서 동작을 변경할 수있는 것은 다른 컨텍스트에서 적절하게 구현하기위한 규칙으로 인터페이스 선언으로 제공됩니다.

편집 : Java 8을 사용하면 인터페이스에서 기본 및 정적 메소드를 쉽게 정의 할 수 있습니다.

public interface SomeInterfaceOne {

    void usualAbstractMethod(String inputString);

    default void defaultMethod(String inputString){
        System.out.println("Inside SomeInterfaceOne defaultMethod::"+inputString);
    }
}

클래스가 SomeInterface를 구현할 때 인터페이스의 기본 메소드에 대한 구현을 반드시 제공 할 필요는 없습니다.

다음 방법으로 다른 인터페이스가있는 경우 :

public interface SomeInterfaceTwo {

    void usualAbstractMethod(String inputString);

    default void defaultMethod(String inputString){
        System.out.println("Inside SomeInterfaceTwo defaultMethod::"+inputString);
    }

}

Java는 컴파일러가 사용할 수퍼 클래스 메소드를 결정할 수없는 "다이아몬드 문제" 가 발생하므로 여러 클래스를 확장 할 수 없습니다. 기본 방법을 사용하면 인터페이스에서도 다이아몬드 문제가 발생합니다. 클래스가 둘 다 구현하는 경우

SomeInterfaceOne and SomeInterfaceTwo

일반적인 기본 방법을 구현하지 않으면 컴파일러가 선택할 방법을 결정할 수 없습니다. 이 문제를 피하려면 Java 8에서는 다른 인터페이스의 공통 기본 메소드를 구현해야합니다. 위의 인터페이스를 모두 구현하는 클래스가있는 경우 defaultMethod () 메서드에 대한 구현을 제공해야합니다. 그렇지 않으면 컴파일러에서 컴파일 시간 오류가 발생합니다.


11
+1, 이것은 혼란을 피하기위한 좋은 해답입니다. 그러나 나는 어떤 링크도 보지 못했고 왜 당신이 그 귀중한 줄을 인용했는지 전혀 모른다. 가능하면 포인트로 만드십시오 :).
Suresh Atta

인터페이스를 사용하고 다른 패밀리의 클래스에 대한 기본 유형을 갖는 인터페이스를 사용하여 다중 상속을 에뮬레이트하는 것에 대한 위의 의견을 읽으십시오. 면접관은 면접에서 이런 종류의 답변을 듣고 싶어한다고 생각합니다.
Francisco Goldenstein

귀하의 의견은 또한 인터페이스의 좋은 예를 지적합니다. 나는 매일 일하면서 느끼는 것을 썼습니다. 이 단어는 전문적이거나 정확하지 않을 수 있습니다. 그러나 일상적인 코딩에서 추상 클래스 및 인터페이스와 긴밀하게 작업 한 후 알게 된 것은 무엇입니까?
Shailesh Saxena

4. 구체적인 구현 또한 기본 구현을 갖는 규칙입니다.
Luten

@Luten : 내 지식에 따라 문제없이 규칙을 피하거나 무시할 수 있다면 규칙이 아닌 지침이어야합니다. 내가 틀렸다면 정정 해주세요.
Shailesh Saxena

168

실제 사용 및 구현의 차이점을 요약했지만 의미의 차이점에 대해서는 언급하지 않았습니다.

인터페이스는 구현 클래스가있을 것이다 동작에 대한 설명입니다. 구현 클래스는 이러한 메소드를 사용할 수 있도록 보장합니다. 그것은 기본적으로 수업이해야 할 계약 또는 약속입니다.

추상 클래스는 반복적으로 생성 할 필요가 없습니다 주 행동이 다른 서브 클래스의 기초입니다. 서브 클래스는 동작을 완료하고 미리 정의 된 동작을 재정의하는 옵션이 있어야합니다 ( final또는로 정의되지 않은 경우 private).

java.util패키지 에서 이미 인터페이스를 구현하는 List것과 같은 인터페이스 와 추상 클래스 를 포함 하는 좋은 예를 찾을 수 AbstractList있습니다. 공식 문서는 설명 AbstractList은 다음과 같습니다 :

이 클래스는 "랜덤 액세스"데이터 저장소 (예 : 배열)로 지원되는이 인터페이스를 구현하는 데 필요한 노력을 최소화하기 위해 List 인터페이스의 골격 구현을 제공합니다.


16
이것이 답이되어야합니다. 세부 사항 목록이 아니라 인터페이스뿐만 아니라 추상 클래스 사이의 차이를 만드는 기본 개념은 Java뿐만 아니라 일반적입니다.
edc65

1
정말 좋습니다. 물론 다른 답변도 좋습니다. 그러나 이것은 abstract키워드에 대한 주요한 결론을 알려줍니다 . 즉, 컴파일러가 이것을 볼 때 다음 정보가 불완전 하며 구현이 필요하다는 것을 알고 있습니다. 인터페이스는 항상 불완전하지만 추상 클래스는 incomplete (abstract)메소드 를 가져야했기 때문에 추상적 입니다.
Rakib

85

인터페이스는 싱글 톤 변수 (공개 정적 최종) 및 공용 추상 메소드로 구성됩니다. 우리는 일반적으로 해야 할 일을 알고 있지만 어떻게 해야할지 모르는 경우 실시간으로 인터페이스를 사용하는 것을 선호 합니다 .

이 개념은 예를 통해 더 잘 이해할 수 있습니다.

지불 클래스를 고려하십시오. 지불은 PayPal, 신용 카드 등과 같은 여러 가지 방법으로 이루어질 수 있습니다. 따라서 일반적으로 makePayment()Method 를 포함하는 인터페이스로 Payment를 사용하고 CreditCard 및 PayPal은 두 가지 구현 클래스입니다.

public interface Payment
{
    void makePayment();//by default it is a abstract method
}
public class PayPal implements Payment
{
    public void makePayment()
    {
        //some logic for PayPal payment
        //e.g. Paypal uses username and password for payment
    }
}
public class CreditCard implements Payment
{
    public void makePayment()
    {
        //some logic for CreditCard payment
        //e.g. CreditCard uses card number, date of expiry etc...
    }
}

위의 예에서 CreditCard와 PayPal은 두 가지 구현 클래스 / 전략입니다. 인터페이스는 또한 추상 클래스로는 달성 할 수없는 Java의 다중 상속 개념을 허용합니다.

우리는 무엇을해야하는지, 수행 방법을 알고있는 다른 기능이있을 때 추상 클래스를 선택합니다 .

다음 예제를 고려하십시오.

public abstract class Burger
{
    public void packing()
    {
        //some logic for packing a burger
    }
    public abstract void price(); //price is different for different categories of burgers
}
public class VegBerger extends Burger
{
    public void price()
    {
        //set price for a veg burger.
    }
}
public class NonVegBerger extends Burger
{
    public void price()
    {
        //set price for a non-veg burger.
    }
}

미래에 주어진 추상 클래스에 메소드 (콘크리트 / 추상)를 추가하면 구현 클래스에서 코드를 변경할 필요가 없습니다. 그러나 나중에 인터페이스에 메소드를 추가하는 경우 해당 인터페이스를 구현 한 모든 클래스에 구현을 추가해야합니다. 그렇지 않으면 컴파일 시간 오류가 발생합니다.

다른 차이점이 있지만 면담자가 예상했던 것과 다른 주요 차이점이 있습니다. 잘만되면 이것이 도움이되었다.


1
글쎄,이 대답은 의미가 있으며, 예를 들어, interface와 사이에서 선택할 때 분명합니다 abstract class.
MAC

인터페이스를 구현할 클래스에서 메소드의 구현을 정의하면서 "void makePayment ();"에 구현을하지 않고 메소드를 정의 할 때 "해야 할 일을 수행하는 방법을 모른다"
압델 - 라우 프

45

Abstact 클래스와 인터페이스의 차이점

  1. Java 8의 추상 클래스와 인터페이스
  2. 개념적 차이 :

Java 8의 인터페이스 기본 메소드

  1. 기본 방법은 무엇입니까?
  2. 기본 메소드를 사용하여 ForEach 메소드 컴파일 오류가 해결되었습니다.
  3. 기본 방법 및 다중 상속 모호성 문제
  4. Java 인터페이스 기본 메소드에 대한 중요한 사항 :

자바 인터페이스 정적 메소드

  1. Java 인터페이스 정적 메소드, 코드 예제, 정적 메소드 및 기본 메소드
  2. Java 인터페이스 정적 메소드에 대한 중요한 사항 :

자바 기능 인터페이스



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

Java 8 인터페이스 변경에는 인터페이스의 정적 메소드 및 기본 메소드가 포함됩니다. Java 8 이전에는 인터페이스에 메소드 선언 만있을 수있었습니다. 그러나 Java 8부터 인터페이스에 기본 메소드와 정적 메소드를 가질 수 있습니다.

기본 메소드를 도입 한 후 인터페이스와 추상 클래스가 동일한 것 같습니다. 그러나 Java 8에서는 여전히 다른 개념입니다.

추상 클래스는 생성자를 정의 할 수 있습니다. 그것들은 더 구조적이고 그들과 관련된 상태를 가질 수 있습니다. 대조적으로, 기본 메소드는 특정 구현 상태를 참조하지 않고 다른 인터페이스 메소드를 호출하는 측면에서만 구현 될 수 있습니다. 따라서 서로 다른 목적으로 사용하고 두 가지 중에서 선택하는 것은 시나리오 상황에 따라 다릅니다.

개념적 차이 :

추상 클래스는 인터페이스의 골격 (즉, 부분) 구현에 유효하지만 일치하는 인터페이스가 없으면 존재하지 않아야합니다.

따라서 추상 클래스가 효과적으로 보이지 않는 인터페이스의 골격 구현으로 축소되면 기본 메소드도 이것을 제거 할 수 있습니까? 결정적으로 : 아니요! 인터페이스를 구현하려면 거의 항상 기본 메소드에없는 클래스 작성 도구의 일부 또는 전부가 필요합니다. 그리고 어떤 인터페이스가 그렇지 않으면 분명히 특별한 경우이며, 당신을 타락으로 이끌지 않아야합니다.

Java 8의 인터페이스 기본 메소드

Java 8에는“ 기본 메소드 ”또는 (수 비기 메소드) 새로운 기능이 도입되어 개발자가 이러한 인터페이스의 기존 구현을 중단하지 않고도 인터페이스에 새로운 메소드를 추가 할 수 있습니다. 구체적인 클래스가 해당 메소드에 대한 구현을 제공하지 못하는 상황에서 기본값으로 사용할 인터페이스 정의 구현을 허용하는 유연성을 제공합니다.

작동 방식을 이해하기 위해 작은 예를 고려하십시오.

public interface OldInterface {
    public void existingMethod();
 
    default public void newDefaultMethod() {
        System.out.println("New default method"
               + " is added in interface");
    }
}

다음 클래스는 Java JDK 8에서 성공적으로 컴파일됩니다.

public class OldInterfaceImpl implements OldInterface {
    public void existingMethod() {
     // existing implementation is here…
    }
}

OldInterfaceImpl 인스턴스를 작성하는 경우 :

OldInterfaceImpl obj = new OldInterfaceImpl ();
// print “New default method add in interface”
obj.newDefaultMethod(); 

기본 방법 :

기본 메소드는 최종적이지 않으며 동기화 할 수 없으며 오브젝트의 메소드를 대체 할 수 없습니다. 그것들은 항상 공개적이며 짧고 재사용 가능한 방법을 작성하는 능력을 심각하게 제한합니다.

기본 메소드는 구현을 포함하므로 클래스 구현에 영향을 미치지 않고 인터페이스에 제공 할 수 있습니다. 구현으로 정의 된 인터페이스의 각 추가 된 메소드는 구현 클래스에 영향을 미치지 않습니다. 구현 클래스는 인터페이스에서 제공하는 기본 구현을 대체 할 수 있습니다.

기본 방법을 사용하면 이러한 인터페이스의 이전 구현을 중단하지 않고 기존 인터페이스에 새로운 기능을 추가 할 수 있습니다.

기본 메소드가 포함 된 인터페이스를 확장하면 다음을 수행 할 수 있습니다.

  1. 기본 방법을 재정의하지 않고 기본 방법을 상속합니다.
  2. 서브 클래스에서 재정의하는 다른 방법과 유사한 기본 방법을 재정의합니다.
  3. 기본 메소드를 abstract로 다시 선언하여 서브 클래스가이를 대체하도록합니다.

기본 메소드를 사용하여 ForEach 메소드 컴파일 오류가 해결되었습니다.

Java 8의 경우 JDK 콜렉션이 확장되었으며 forEach 메소드가 전체 콜렉션에 추가되었습니다 (람다와 함께 작동 함). 일반적인 방법으로 코드는 다음과 같습니다.

public interface Iterable<T> {
    public void forEach(Consumer<? super T> consumer);
}

따라서 결과적으로 컴파일 오류가있는 각 구현 클래스가 있으므로 기존 구현을 변경하지 않도록 필수 구현으로 기본 메소드를 추가했습니다.

기본 메소드를 사용한 반복 인터페이스는 다음과 같습니다.

public interface Iterable<T> {
    public default void forEach(Consumer
                   <? super T> consumer) {
        for (T t : this) {
            consumer.accept(t);
        }
    }
}

구현 클래스를 손상시키지 않고 JDK 인터페이스 에 스트림 을 추가하는 데 동일한 메커니즘이 사용되었습니다 .


기본 방법 및 다중 상속 모호성 문제

java 클래스는 여러 인터페이스를 구현할 수 있고 각 인터페이스는 동일한 메소드 서명으로 기본 메소드를 정의 할 수 있으므로 상속 된 메소드가 서로 충돌 할 수 있습니다.

아래 예를 고려하십시오.

public interface InterfaceA {  
       default void defaultMethod(){  
           System.out.println("Interface A default method");  
    }  
}
 
public interface InterfaceB {
   default void defaultMethod(){
       System.out.println("Interface B default method");
   }
}
 
public class Impl implements InterfaceA, InterfaceB  {
}

위의 코드는 다음 오류로 컴파일되지 않습니다.

java : Impl 클래스는 InterfaceA 및 InterfaceB 유형에서 defaultMethod ()에 대해 관련되지 않은 기본값을 상속합니다.

이 클래스를 수정하려면 기본 메소드 구현을 제공해야합니다.

public class Impl implements InterfaceA, InterfaceB {
    public void defaultMethod(){
    }
}

또한 자체 구현이 아닌 수퍼 인터페이스에서 제공하는 기본 구현을 호출하려는 경우 다음과 같이 수행 할 수 있습니다.

public class Impl implements InterfaceA, InterfaceB {
    public void defaultMethod(){
        // existing code here..
        InterfaceA.super.defaultMethod();
    }
}

우리는 새로운 방법의 일부로 기본 구현 또는 둘 다를 선택할 수 있습니다.

Java 인터페이스 기본 메소드에 대한 중요한 사항 :

  1. Java 인터페이스 기본 메소드는 구현 클래스를 중단 할 염려없이 인터페이스를 확장하는 데 도움이됩니다.
  2. Java 인터페이스 기본 메소드는 인터페이스와 추상 클래스의 차이점을 보완합니다.
  3. Java 8 인터페이스 기본 메소드는 모든 Collections 클래스 메소드가 인터페이스 자체에서 제공 될 수있는 것과 같은 유틸리티 클래스를 피하는 데 도움이됩니다.
  4. Java 인터페이스 기본 메소드는 기본 구현 클래스를 제거하는 데 도움이되고 기본 구현을 제공 할 수 있으며 구현 클래스는 대체 할 클래스를 선택할 수 있습니다.
  5. 인터페이스에 기본 메소드를 도입 한 주요 이유 중 하나는 람다 표현식을 지원하도록 Java 8에서 Collections API를 향상시키는 것입니다.
  6. 계층 구조의 클래스에 서명이 동일한 메소드가있는 경우 기본 메소드는 관련이 없습니다. 기본 메소드는 java.lang.Object의 메소드를 대체 할 수 없습니다. 추론은 매우 간단합니다. Object는 모든 Java 클래스의 기본 클래스이기 때문입니다. 따라서 인터페이스에 기본 메소드로 정의 된 Object 클래스 메소드가 있더라도 Object 클래스 메소드가 항상 사용되므로 쓸모가 없습니다. 그렇기 때문에 혼동을 피하기 위해 Object 클래스 메서드를 재정의하는 기본 메서드를 가질 수 없습니다.
  7. Java 인터페이스 기본 메소드는 Defender 메소드 또는 가상 확장 메소드라고도합니다.

리소스 링크 :

  1. Java 8의 기본 메소드와 추상 클래스가있는 인터페이스
  2. JDK 8 시대의 추상 클래스와 인터페이스
  3. 가상 확장 방법을 통한 인터페이스 진화

자바 인터페이스 정적 메소드

Java 인터페이스 정적 메소드, 코드 예제, 정적 메소드 및 기본 메소드

Java 인터페이스 정적 메소드는 구현 클래스에서이를 대체 할 수 없다는 점을 제외하고 기본 메소드와 유사합니다. 이 기능은 구현 클래스에서 구현이 잘못되었을 때 원하지 않는 결과를 피하는 데 도움이됩니다. 간단한 예를 통해이를 살펴 보겠습니다.

public interface MyData {

    default void print(String str) {
        if (!isNull(str))
            System.out.println("MyData Print::" + str);
    }

    static boolean isNull(String str) {
        System.out.println("Interface Null Check");

        return str == null ? true : "".equals(str) ? true : false;
    }
}

이제 구현이 좋지 않은 isNull () 메소드가있는 구현 클래스를 보자.

public class MyDataImpl implements MyData {

    public boolean isNull(String str) {
        System.out.println("Impl Null Check");

        return str == null ? true : false;
    }

    public static void main(String args[]){
        MyDataImpl obj = new MyDataImpl();
        obj.print("");
        obj.isNull("abc");
    }
}

isNull (String str)은 간단한 클래스 메서드이며 인터페이스 메서드를 재정의하지 않습니다. 예를 들어, @Nride () 메소드에 @Override 어노테이션을 추가하면 컴파일러 오류가 발생합니다.

이제 우리는 응용 프로그램을 실행할 때 다음과 같은 결과를 얻습니다.

인터페이스 널 점검

Impl 널 점검

인터페이스 메소드를 정적에서 기본값으로 만들면 다음과 같은 출력이 나타납니다.

Impl 널 점검

MyData 인쇄 ::

Impl 널 점검

Java 인터페이스 정적 메소드는 인터페이스 메소드에만 표시됩니다. MyDataImpl 클래스에서 isNull () 메소드를 제거하면 MyDataImpl 오브젝트에이 메소드를 사용할 수 없습니다. 그러나 다른 정적 메소드와 마찬가지로 클래스 이름을 사용하여 인터페이스 정적 메소드를 사용할 수 있습니다. 예를 들어 유효한 진술은 다음과 같습니다.

boolean result = MyData.isNull("abc");

Java 인터페이스 정적 메소드에 대한 중요한 사항 :

  1. Java 인터페이스 정적 메소드는 인터페이스의 일부이므로 구현 클래스 객체에 사용할 수 없습니다.
  2. Java 인터페이스 정적 메소드는 유틸리티 메소드 (예 : 널 검사, 콜렉션 정렬 등)를 제공하는 데 유용합니다.
  3. Java 인터페이스 정적 메소드는 구현 클래스가이를 대체하지 못하도록하여 보안을 제공하는 데 도움이됩니다.
  4. Object 클래스 메소드에 대한 인터페이스 정적 메소드를 정의 할 수 없습니다.“이 정적 메소드는 Object에서 인스턴스 메소드를 숨길 수 없습니다”라는 컴파일러 오류가 발생합니다. Object는 모든 클래스의 기본 클래스이므로 동일한 서명을 가진 하나의 클래스 레벨 정적 메소드와 다른 인스턴스 메소드를 가질 수 없으므로 java에서는 허용되지 않기 때문입니다.
  5. java 인터페이스 정적 메소드를 사용하여 Collections와 같은 유틸리티 클래스를 제거하고 모든 정적 메소드를 해당 인터페이스로 이동하여 쉽게 찾고 사용할 수 있습니다.

자바 기능 인터페이스

게시물을 마치기 전에 Functional 인터페이스에 대해 간략하게 소개하고 싶습니다. 정확히 하나의 추상 메소드가있는 인터페이스를 기능 인터페이스라고합니다.

@FunctionalInterface인터페이스를 기능 인터페이스로 표시하기 위해 새로운 주석 이 도입되었습니다. @FunctionalInterface주석은 기능 인터페이스에 추상적 인 메소드가 실수로 추가되는 것을 방지하는 기능입니다. 선택이지만 사용하는 것이 좋습니다.

함수형 인터페이스는 오랫동안 기다려 왔으며, 람다 식을 사용하여 인스턴스화 할 수 있기 때문에 Java 8의 기능을 많이 찾고 있습니다. 람다 식 및 메소드 참조에 대한 대상 유형을 제공하기 위해 기능 인터페이스가 많은 새 패키지 java.util.function이 추가되었습니다. 향후 포스트에서 기능적 인터페이스와 람다 식을 살펴볼 것입니다.

자원 위치 :

  1. Java 8 인터페이스 변경 – 정적 메소드, 기본 메소드

8
이러한 유형의 업데이트 된 답변을 정확하게 찾고 있습니다. 빠른 답변 감사합니다.
Ravindra babu

41

첫 번째 진술 (Java 8 릴리스 이후)을 제외한 모든 진술이 유효합니다.

Java 인터페이스의 메소드는 내재적으로 추상적이며 구현할 수 없습니다

설명서 페이지에서 :

인터페이스는 클래스와 유사하며 상수, 메소드 서명, 기본 메소드, 정적 메소드 및 중첩 유형 만 포함 할 수있는 참조 유형입니다.

메소드 본문은 기본 메소드 및 정적 메소드에만 존재합니다.

기본 방법 :

인터페이스는 기본 메소드 를 가질 수 있지만 추상 클래스의 추상 메소드와 다릅니다.

기본 방법을 사용하면 라이브러리의 인터페이스에 새로운 기능을 추가하고 해당 인터페이스의 이전 버전 용으로 작성된 코드와 이진 호환성을 보장 할 수 있습니다.

기본 메소드가 포함 된 인터페이스를 확장하면 다음을 수행 할 수 있습니다.

  1. 기본 메소드를 언급하지 않아도 확장 인터페이스가 기본 메소드를 상속 할 수 있습니다.
  2. 기본 메소드를 다시 선언하면됩니다 abstract.
  3. 재정의하는 기본 방법을 재정의하십시오.

정적 방법 :

기본 메소드 외에도 인터페이스에서 정적 메소드를 정의 할 수 있습니다. (정적 메소드는 객체가 아니라 정의 된 클래스와 연관된 메소드입니다. 클래스의 모든 인스턴스는 정적 메소드를 공유합니다.)

이를 통해 라이브러리에서 헬퍼 메소드를 쉽게 구성 할 수 있습니다.

interface보유 staticdefault방법 에 대한 설명서 페이지의 예제 코드

import java.time.*;

public interface TimeClient {
    void setTime(int hour, int minute, int second);
    void setDate(int day, int month, int year);
    void setDateAndTime(int day, int month, int year,
                               int hour, int minute, int second);
    LocalDateTime getLocalDateTime();

    static ZoneId getZoneId (String zoneString) {
        try {
            return ZoneId.of(zoneString);
        } catch (DateTimeException e) {
            System.err.println("Invalid time zone: " + zoneString +
                "; using default time zone instead.");
            return ZoneId.systemDefault();
        }
    }

    default ZonedDateTime getZonedDateTime(String zoneString) {
        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
    }
}

아래 지침을 사용하여 인터페이스 또는 추상 클래스 사용 여부를 선택하십시오.

상호 작용:

  1. 계약 을 정의하려면 (바람직하게는 상태 비 저장-변수 없음)
  2. 관련없는 클래스를 연결 하는 기능이 있습니다.
  3. 공개 상수 변수를 선언하려면 ( 불변 상태 )

추상 클래스 :

  1. 밀접하게 관련된 여러 클래스간에 코드를 공유하십시오. 관계를 확립 한다 .

  2. 관련 클래스 간에 공통 상태 공유 (구체적인 클래스에서 상태를 수정할 수 있음)

관련 게시물:

인터페이스 대 추상 클래스 (일반 OO)

구현 및 확장 : 사용시기 차이점이 뭐야?

이 예제들을 살펴보면

관련없는 클래스는 인터페이스를 통해 기능을 가질 수 있지만 관련 클래스는 기본 클래스의 확장을 통해 동작을 변경합니다.


"무국적 계약"이란 무슨 뜻입니까? 이 인터페이스에 대한 항목 1의
막심 드미트리

1
변경 가능한 상태가 없습니다. 인터페이스는 상수를 가질 수 있기 때문에, 데이터는 추상 클래스와는 달리 돌연변이 될 수있다
라빈 드라 BABU

1
위 진술의 수정. 인터페이스에서 추상 클래스와 달리 데이터를 변경할 수 없음
Ravindra babu

2
이것이 가장 좋은 대답입니다. Java8을 해결할뿐만 아니라 어떤 상황에서 어느 쪽을 사용할 것인지도 설명합니다.
Shuklaswag

stateless인터페이스 의 개념은 대히트입니다. 인터페이스는 어떤 상태도 가질 수 없습니다 (인터페이스는 상수를 가질 수 있지만 최종 / 정적이므로 변경할 수 없습니다).
Kaihua

22

설명은 괜찮은 것처럼 보이지만 교과서에서 모두 읽은 것처럼 보일 수 있습니까? :-/

내가 더 걱정하는 것은 당신의 모범이 얼마나 견고 했습니까? 추상과 인터페이스의 거의 모든 차이점 을 포함 시키려 했습니까 ?

개인적으로, 나는이 링크를 제안합니다 : http://mindprod.com/jgloss/interfacevsabstract.html#TABLE

철저한 차이점 목록 ..

앞으로의 인터뷰에서 당신과 다른 모든 독자들을 도울 수 있기를 바랍니다.


1
링크가 공유되었습니다 정말 최고입니다
Premraj

기본 키워드를 사용하여 Java 인터페이스에서 기본 구현을 제공 할 수 있습니다.
Ogen

21

많은 주니어 개발자들은 인터페이스, 추상 및 구체적인 클래스를 같은 것의 약간의 변형으로 생각하는 실수를 저지르고 기술적 인 측면에서 순수하게 선택 합니다. 다중 상속이 필요합니까? 일반적인 방법을 사용하려면 장소가 필요합니까? 구체적인 수업 이외의 다른 것을 귀찮게해야합니까? 이것은 잘못이며,이 질문에 숨겨져의 주요 문제 : "I" . 혼자서 코드를 작성할 때, 현재 또는 미래의 다른 개발자가 코드를 다루거나 작업하는 것을 거의 생각하지 않습니다.

인터페이스와 추상 클래스는 기술적 인 관점에서 분명히 비슷하지만 완전히 다른 의미와 목적을 가지고 있습니다.

요약

  1. 인터페이스 일부 구현이 수행 할 계약정의 합니다 .

  2. 추상 클래스 구현에서 재사용 할 수 있는 기본 동작제공합니다 .

위의 두 가지 사항은 인터뷰 할 때 찾고자하는 내용이며 요약이 충분합니다. 자세한 내용은 계속 읽으십시오.

대체 요약

  1. 공용 API를 정의하기위한 인터페이스
  2. 추상 클래스는 내부 용 및 SPI 정의용입니다.

예를 들어

다르게 말하자면 : 구체적인 수업은 실제 작업을 매우 특정한 방식으로 수행합니다. 예를 들어, ArrayLista는 연속적인 메모리 영역을 사용하여 빠른 무작위 액세스, 반복 및 내부 변경을 제공하지만 삽입, 삭제 및 때로는 추가시에는 끔찍한 방식으로 객체 목록을 압축 방식으로 저장합니다. 한편,LinkedList이중 링크 노드를 사용하여 객체 목록을 저장합니다. 대신 빠른 반복, 전체 변경, 삽입 / 삭제 / 추가를 제공하지만 임의 액세스에서는 끔찍합니다. 이 두 가지 유형의 목록은 다양한 사용 사례에 최적화되어 있으며 사용 방법에 매우 중요합니다. 상호 작용하는 목록에서 성능을 끌어 내려고 할 때 목록 유형을 선택할 때 자신이 원하는 항목을 신중하게 선택해야합니다.

반면에, 목록의 고급 사용자는 실제로 어떻게 구현되는지 신경 쓰지 않으며, 이러한 세부 사항으로부터 격리되어야합니다. Java가 List인터페이스를 공개하지는 않았지만 List실제로 LinkedList는 현재 구체적인 클래스 만 가지고 있다고 상상해 봅시다 . 모든 Java 개발자는 구현 세부 사항에 맞게 코드를 조정했습니다. 임의의 액세스를 피하고 캐시를 추가하여 액세스 속도를 높이거나 ArrayList자체적으로 다시 구현 하지만 실제로는 다른 코드와 호환되지 않습니다.List 합니다. . 그것은 끔찍할 것입니다 ...하지만 이제 Java 마스터는 실제로 링크 된 목록이 대부분의 실제 사용 사례에서 끔찍하다는 것을 알고 자신의 배열 목록으로 전환하기로 결정했다고 상상해보십시오.List유효한 수업. 이것은 전 세계 모든 Java 프로그램의 성능에 영향을 미치며 사람들은 그것에 만족하지 않을 것입니다. 그리고 주요 원인은 구현 세부 사항을 사용할 수 있다는 것이며 개발자는 이러한 세부 사항을 신뢰할 수있는 영구 계약이라고 가정했습니다. 그렇기 때문에 구현 세부 사항을 숨기고 추상 계약 만 정의하는 것이 중요합니다. 이것은 인터페이스의 목적입니다. 프로그래머가 미래의 업데이트로 변경 될 수있는 내부 세부 사항에 맞게 코드를 조정하도록 유혹하는 모든 용기를 노출시키지 않으면 서 메소드가 허용하는 입력 종류와 예상되는 출력 종류를 정의하십시오. .

인터페이스와 구체적인 클래스 사이에 추상 클래스가 있습니다. 구현이 공통 또는 지루한 코드를 공유하는 데 도움이됩니다. 예를 들어, AbstractCollection기본적인 구현을 제공 isEmpty크기에 기초가 0 contains으로 반복하고, 비교로서, addAll반복적으로 add, 등등. 이를 통해 구현은 데이터를 실제로 저장하고 검색하는 방법과 차별화하는 중요한 부분에 집중할 수 있습니다.

다른 관점 : API와 SPI

인터페이스는 코드의 다른 부분들 사이의 응집력이 낮은 게이트웨이 입니다. 내부적으로 변경 될 때 모든 라이브러리 사용자를 방해하지 않고 라이브러리가 존재하고 진화 할 수 있습니다. 그것은라고 프로그래밍 응용 프로그램 인터페이스 가 아닌 응용 프로그래밍 클래스. 더 작은 규모에서는 여러 개발자가 잘 문서화 된 인터페이스를 통해 다른 모듈을 분리하여 대규모 프로젝트에서 성공적으로 협업 할 수 있습니다.

추상 클래스는 인터페이스를 구현할 때 일정 수준의 구현 세부 사항을 가정 할 때 응집력이 높은 도우미 입니다. 또는 추상 클래스가 SPI, 서비스 제공자 인터페이스를 정의하는 데 사용됩니다.

API와 SPI의 차이는 미묘하지만 중요합니다. API의 경우 API를 사용 하는 사람 에 중점을두고 SPI의 경우이를 구현 하는 사람에 중점을 둡니다 .

API에 메소드를 추가하는 것은 쉽습니다. API의 모든 기존 사용자는 여전히 컴파일됩니다. 모든 서비스 제공 업체 (콘크리트 구현)가 새 메소드를 구현해야하므로 SPI에 메소드를 추가하는 것은 어렵습니다. 인터페이스가 SPI를 정의하는 데 사용되는 경우 공급자는 SPI 계약이 변경 될 때마다 새 버전을 릴리스해야합니다. 추상 클래스가 대신 사용되는 경우 새 메소드는 기존 추상 메소드 또는 빈 throw not implemented exception스텁 으로 정의 될 수 있습니다.이 경우 스텁은 최소한 이전 버전의 서비스 구현이 여전히 컴파일 및 실행되도록 허용합니다.

Java 8 및 기본 메소드에 대한 참고 사항

Java 8은 인터페이스와 추상 클래스 사이의 경계를 더욱 흐리게 만드는 인터페이스에 대한 기본 메소드를 도입했지만, 구현이 코드를 재사용 할 수 있도록하는 것이 아니라 API와 SPI 모두를 제공하는 인터페이스를보다 쉽게 ​​변경할 수있었습니다. (또는 추상 클래스 대신 SPI를 정의하는 데 잘못 사용됨).

"도서 지식"

OP의 답변에 제공된 기술적 세부 사항은 일반적으로 학교와 대부분의 기술 서적에서 사용되는 언어에 대한 접근 방식이기 때문에 "책 지식"으로 간주됩니다. 실제로 대규모 응용 프로그램에서 실제로 사용 하는 방법 이 아니라 무엇인가 .

여기에 비유가 있습니다. 질문은 다음과 같습니다.

무도회 밤, 자동차 또는 호텔 방 임대가 더 좋습니까?

기술 답변은 다음과 같습니다.

글쎄, 차 안에서는 빨리 할 수 ​​있지만 호텔 방에서는 더 편안하게 할 수 있습니다. 반면에 호텔 객실은 한 곳에만 있고 차 안에서는 더 많은 곳에서 할 수 있습니다. 예를 들어 전망대에 가면 멋진 경치를 보거나 운전 극장에서 또는 다른 많은 장소, 또는 둘 이상의 장소. 또한 호텔 객실에는 샤워 시설이 있습니다.

그것은 사실이지만, 그것들이 완전히 다른 두 가지라는 점을 완전히 그리워하며, 둘 다 다른 목적으로 동시에 사용될 수 있으며, "수행"측면이 두 옵션 중 하나에 대해 가장 중요한 것은 아닙니다. . 대답은 원근법이없고, 미묘한 사고 방식을 보여 주면서도 사실 인 "사실"을 정확하게 제시합니다.


"저 커플 링"을 의미 했습니까?
user2418306

@ user2418306 아니요, 응집력은 커플 링을 포함하는 좀 더 일반적인 용어입니다.
Sergiu Dumitriu

9

다음과 같이 생각하면 어떨까요?

  • 클래스와 추상 클래스 간의 관계는 "is-a"유형입니다.
  • 클래스와 인터페이스의 관계는 "has-a"유형입니다.

따라서 추상 클래스 Mammals, 하위 클래스 Human 및 인터페이스 Driving이 있으면 말할 수 있습니다.

  • 각각의 인간은 포유류
  • 각 인간에게는 운전 (행동)

저의 제안은 책 지식 문구가 그가 (이미 다른 사람들이 이미 제안한 것처럼) 둘 사이의 의미 론적 차이를 듣고 싶어한다는 것을 나타냅니다.


9

인터페이스는 계약을 구현하는 클래스가 메소드를 구현할 것을 약속하는 "계약"입니다. 클래스 대신 인터페이스를 작성해야하는 예는 게임을 2D에서 3D로 업그레이드 할 때였습니다. 게임의 2D와 3D 버전간에 클래스를 공유하기위한 인터페이스를 만들어야했습니다.

package adventure;
import java.awt.*;
public interface Playable {
    public void playSound(String s);
    public Image loadPicture(String s);    
}

그런 다음 환경에 따라 메서드를 구현할 수 있지만로드중인 게임 버전을 모르는 개체에서 해당 메서드를 계속 호출 할 수 있습니다.

public class Adventure extends JFrame implements Playable

public class Dungeon3D extends SimpleApplication implements Playable

public class Main extends SimpleApplication implements AnimEventListener, ActionListener, Playable

일반적으로 게임 세계에서 세계는 게임에서 메서드를 수행하는 추상 클래스가 될 수 있습니다.

public abstract class World...

    public Playable owner;

    public Playable getOwner() {
        return owner;
    }

    public void setOwner(Playable owner) {
        this.owner = owner;
    }

6

추상 클래스는 구현되지 않은 메소드뿐만 아니라 콘크리트 (구현 된 메소드)의 콜렉션으로 순수한 추상화가 아닙니다. 그러나 인터페이스는 순수한 추상화입니다. 구체적인 방법이 아닌 구현되지 않은 방법 만 있습니다.

왜 추상 클래스입니까?

  1. 사용자가 모든 객체에 공통 기능을 작성하려면.
  2. 최종 사용자에게 영향을 미치지 않고 더 많은 기능을 추가 할 수 있도록 추상 클래스는 향후 재 구현에 가장 적합한 선택입니다.

왜 인터페이스인가?

  1. 사용자가 다른 기능을 작성하려는 경우 객체에서 다른 기능을 수행합니다.
  2. 인터페이스가 게시 된 후 요구 사항을 수정할 필요가없는 경우 인터페이스를 선택하는 것이 가장 좋습니다.

5

인터페이스는 공개적으로 효과의 일종 가지고 문서화되어 유전자의 집합 같다 : DNA를 테스트는 내가 그들을 가지고 있는지 말해 것이다 - 그리고 내가 할 경우, 나는 공개적으로는 나는 "캐리어 해요 것을 알 수 있습니다 "및 내 행동 또는 상태의 일부가이를 준수합니다. (물론이 범위 밖에서 특성을 제공하는 다른 많은 유전자가있을 수 있습니다.)

추상 클래스는 a의 죽은 조상처럼 단일 섹스 종 그녀는 삶에 가져온 할 수 없지만 살아있는 (예 : (*) 이 아닌 추상적 인 ) 자손 상속 그녀의 모든 유전자.

(*)이 은유를 늘리기 위해 모든 종의 구성원이 같은 나이에 살고 있다고합시다. 이것은 죽은 조상의 모든 조상도 죽어야한다는 것을 의미합니다. 마찬가지로 살아있는 조상의 모든 후손도 살아 있어야합니다.


4

나는 일에 대한 인터뷰를하고 당신의 대답에 대해 바람직하지 않게 보일 것입니다 (죄송하지만 정직합니다). 차이점에 대해 읽고 답을 수정 한 것처럼 들리지만 실제로는 사용하지 않은 것 같습니다.

각각을 사용하는 이유에 대한 좋은 설명은 차이점에 대한 정확한 설명보다 훨씬 낫습니다. 고용주 ultimatley는 프로그래머가 인터뷰에서 시연하기 어려운 것을 모르는 일을하기를 원합니다. 기술 또는 문서 기반 작업을 신청하지만 개발자 역할이 아닌 경우 귀하가 제공 한 답변이 좋습니다.

미래의 인터뷰에 행운을 빕니다.

또한이 질문에 대한 나의 대답은 당신이 제공 한 기술 자료보다는 인터뷰 기술에 관한 것입니다. 아마도 그것에 대해 읽어보십시오. https://workplace.stackexchange.com/ 이 이런 종류의 장소에 훌륭한 장소가 될 수 있습니다.


1
어떻게 대답했는지 말씀해 주시겠습니까? 도움이 될 수 있습니다.
code_fish

당신에게 대답을 제공하는 것이 훨씬 적을뿐 아니라 그것을 해결하는 데 도움이됩니다.
Adrian

4

다중 상속에서 다이아몬드 문제 를 피하려면 Java에서 인터페이스를 선택합니다 .

클라이언트가 모든 메소드를 구현하려면 인터페이스로 이동하십시오. 그것은 전체 애플리케이션을 추상적으로 디자인한다는 것을 의미합니다.

공통점이 무엇인지 이미 알고 있다면 추상 클래스를 선택합니다. 예를 들어 추상 클래스를 사용하십시오 Car. 더 높은 수준에서는 다음과 같은 일반적인 자동차 메소드를 구현합니다 calculateRPM(). 일반적인 방법이며 클라이언트가 자신과 같은 고유 한 동작을 구현하게합니다
calculateMaxSpeed(). 일상 업무에서 접한 실시간 예제는 거의 제공하지 않았을 것입니다.



3

내가 관찰 한 주요 차이점은 추상 클래스가 이미 구현 된 일반적인 동작을 제공하고 하위 클래스는 해당 기능을 구현하기 만하면된다는 것입니다. 여기서 인터페이스는 수행해야 할 작업 만 지정하며 인터페이스로 구현이 제공되지 않습니다. 자체 클래스와 구현 클래스 간의 계약을 지정한다고 말할 수 있습니다.


3

심지어 여러 번의 인터뷰에서 같은 질문에 직면하여 인터뷰 한 사람을 설득하는 것이 당신의 시간을 비참하게 만든다고 믿습니다. 위의 모든 답변을 내재하면 OO를 최대한 설득하고 최대한 활용하기 위해 하나의 핵심 사항을 추가해야합니다.

규칙에서 수정을 계획하지 않는 경우 하위 클래스를 따르려면 오랫동안 인터페이스를 수정할 수 없으므로 인터페이스로 이동하십시오. 그렇다면 수정해야합니다. 다른 모든 하위 클래스의 변경 사항을 생각하지만 기능을 재사용하고 규칙을 설정하고 수정을 위해 열어 두려면 Abstract 클래스로 이동하십시오.

이런 식으로 생각하면 소모품 서비스를 사용했거나 세계에 코드를 제공했으며 무언가를 수정할 수있는 기회가 있으며 보안 검사를 가정하고 코드 소비자이며 업데이트 후 어느 날 아침 내 Eclipse에서 모든 읽기 표시를 찾으십시오. 전체 응용 프로그램이 다운되었습니다. 이러한 악몽을 막으려면 Abstract over Interfaces를 사용하십시오.

나는 이것이 면접관을 어느 정도 설득시킬 수 있다고 생각합니다 ... 행복한 인터뷰.


2

밀접하게 관련된 두 클래스 사이에서 동작을 공유하려고 할 때 공통 동작을 유지하고 두 클래스의 부모 역할을하는 추상 클래스를 만듭니다.

Type, 객체의 사용자가 안정적으로 호출 할 수있는 메소드 목록을 정의하려고하면 인터페이스를 만듭니다.

예를 들어 추상 클래스는 동작 공유에 관한 것이므로 구체적인 하위 클래스가 1 개인 추상 클래스를 만들지 않습니다. 그러나 하나의 구현으로 인터페이스를 만들 수 있습니다. 내 코드 사용자는 구현이 하나만 있다는 것을 알지 못합니다. 실제로, 다음 릴리스에서는 몇 가지 구현이있을 수 있습니다.이 구현은 모두 인터페이스를 만들 때조차 없었던 새로운 추상 클래스의 하위 클래스입니다.

그것은 너무 너무 책장처럼 보일 수도 있습니다. 면접관 (또는 OP)이 실제로 내 개인적인 경험을 더 원한다면 인터페이스의 필요성에 대한 일화가 생겼을 것입니다.

하나 더. Java 8에서는 인터페이스와 추상 클래스 사이의 경계를 더욱 흐리게하여 기본 코드를 인터페이스에 넣을 수 있습니다. 그러나 내가 본 것으로부터, 그 기능은 Java 핵심 라이브러리의 제조사조차도 남용합니다. 이 기능은 바이너리 비 호환성을 만들지 않고 인터페이스를 확장 할 수 있도록 추가되었습니다. 그러나 인터페이스를 정의하여 새로운 유형을 만드는 경우 인터페이스는 인터페이스 일뿐입니다. 공통 코드를 제공하려면 항상 도우미 클래스를 작성하십시오 (추상 또는 구체적). 변경하려는 기능으로 인터페이스를 처음부터 복잡하게 만들지 마십시오.


2

인터페이스와 추상 클래스의 기본 차이점은 인터페이스가 다중 상속을 지원하지만 추상 클래스는 지원하지 않는다는 것입니다.

추상 클래스에서도 인터페이스와 같은 모든 추상 메소드를 제공 할 수 있습니다.

왜 추상 클래스가 필요한가요?

일부 시나리오에서 사용자 요청을 처리하는 동안 추상 클래스는 사용자 의도를 알지 못합니다. 이 시나리오에서는 클래스에서 하나의 추상 메소드를 정의하고이 클래스를 확장 한 사용자에게 요청하여 추상 메소드에서 의도를 제공하십시오. 이 경우 추상 클래스는 매우 유용합니다

왜 인터페이스가 필요한가요?

그 분야에서 경험이없는 작품이 있다고 가정 해 봅시다. 예를 들어 건물이나 댐을 건설하려는 경우 해당 시나리오에서 무엇을 하시겠습니까?

  1. 요구 사항이 무엇인지 식별하고 해당 요구 사항과 계약을 체결합니다.
  2. 그런 다음 텐더에게 전화하여 프로젝트를 구성하십시오.
  3. 누가 프로젝트를 구성하든 요구 사항을 충족해야합니다. 그러나 구성 로직은 공급 업체마다 다릅니다.

여기서 나는 그들이 어떻게 구성했는지에 대해 신경 쓰지 않습니다. 최종 목표는 내 요구 사항을 충족시키는 지 여부, 그것이 핵심 요점이었습니다.

여기서 인터페이스 및 생성자라는 요구 사항을 구현 자라고합니다.


2

몇 마디로, 나는 이런 식으로 대답 할 것입니다 :

  • 클래스 계층을 통한 상속은 상태 상속을 의미합니다 .
  • 인터페이스를 통한 상속은 행동 상속을 나타냅니다 .

추상 클래스는이 두 경우 사이에서 무언가로 취급 될 수 있습니다 (일부 상태를 도입하지만 행동을 정의해야합니다). 완전히 추상적 인 클래스는 인터페이스입니다 (이 클래스는 C ++의 가상 메소드로만 구성됩니다. 구문을 알고있는 한).

물론 Java 8부터는 약간 변경되었지만 아이디어는 여전히 동일합니다.

컴파일러 팀과 인터뷰하지 않으면 일반적인 Java 인터뷰에 충분하다고 생각합니다.


1

내가 이해 한 바에 따르면, 구현이없는 최종 변수와 메소드로 구성된 인터페이스는 클래스로 구현되어 서로 관련된 메소드 또는 메소드 그룹을 얻습니다. 다른 한편으로, 구현이 아닌 비 최종 변수 및 메소드를 포함 할 수있는 추상 클래스는 일반적으로 모든 관련 또는 유사한 클래스가 상속하는 안내서 또는 수퍼 클래스로 사용됩니다. 다시 말해서, 추상 클래스는 모든 서브 클래스가 공유하는 모든 메소드 / 변수를 포함합니다.


1

추상 클래스에서는 기본 메소드 구현을 작성할 수 있습니다! 그러나 인터페이스에서는 할 수 없습니다. 기본적으로 인터페이스에는 인터페이스를 구현하는 클래스에 의해 구현되어야하는 순수한 가상 메소드가 있습니다.


1

그렇습니다. 귀하의 답변은 기술적으로 정확했지만 귀하가 잘못한 곳에서 답변을 표시하지 않았으므로 다른 것을 선택하는 것의 장점과 단점을 이해합니다. 또한 향후 업그레이드와 코드베이스의 호환성에 대해 염려하거나 걱정했을 것입니다. 이러한 유형의 응답이 도움이 될 수 있습니다 (말한 내용 외에도).

"인터페이스 클래스를 통해 추상 클래스를 선택하는 것은 코드의 미래를 예측하는 것에 달려 있습니다.

추상 클래스는 기존 코드를 손상시키지 않고 미래에 추상 클래스에 동작을 계속 추가 할 수 있기 때문에보다 나은 호환성을 제공합니다. 인터페이스 클래스로는 불가능합니다.

반면에 인터페이스 클래스는 추상 클래스보다 융통성이 있습니다. 여러 인터페이스를 구현할 수 있기 때문입니다 입니다. Java에는 다중 상속이 없으므로 추상 클래스를 사용하면 다른 클래스 계층 구조를 사용할 수 없습니다 ...

결국, 일반적인 일반적인 경험 규칙은 다음과 같습니다. 코드베이스에 기존 / 기본 구현이없는 경우 인터페이스 클래스를 사용하는 것이 좋습니다. 앞으로 클래스를 업데이트 할 예정인 경우 추상 클래스를 사용하여 호환성을 유지하십시오. "

다음 인터뷰에서 행운을 빕니다!


1

실용적인 시나리오를 사용하여 두 가지의 차이점을 보여 주려고 노력할 것입니다.

인터페이스에는 페이로드가 제로가 없으므로 상태를 유지할 필요가 없으므로 계약 (기능)을 클래스와 연결하는 것이 더 좋습니다.

예를 들어, 작업을 수행하는 Task 클래스가 있다고 가정 해 봅시다. 이제 별도의 스레드에서 작업을 실행하려면 실제로 Thread 클래스를 확장 할 필요는 없습니다. ) 그런 다음이 Task 클래스의 객체를 Thread 인스턴스에 전달하고 start () 메서드를 호출하십시오.

이제 Runnable이 추상 클래스인지 물어볼 수 있습니다.

기술적으로는 가능하지만 디자인상의 현명한 선택의 여지가없는 선택은 다음과 같습니다.

  • Runnable은 이와 연관된 상태가 없으며 run () 메소드에 대한 기본 구현을 '제공'하지도 않습니다
  • 작업은 다른 클래스를 확장 할 수 없도록 확장해야합니다.
  • 작업은 Runnable 클래스에 대한 전문화로 제공 할 것이 없으며 run () 메서드를 재정의하는 것만 필요합니다.

다시 말해, Task 클래스는 Thread 클래스를 확장하는 Runnable 인터페이스 구절을 구현함으로써 스레드에서 실행될 수있는 기능이 필요했습니다.

단순히 기능 (계약)을 정의하기위한 인터페이스를 제공하는 동시에 추상 클래스를 사용하여 기능 (일반 / 부분) 구현을 정의하십시오.

면책 조항 : 어리석은 예는 다음과 같습니다.

interface Forgiver {
    void forgive();
}

abstract class GodLike implements Forgiver {
    abstract void forget();
    final void forgive() {
        forget();
    }
}

이제 당신은 GodLike가 될 수있는 선택권을 받았지만, 당신은 용서 자 (즉 GodLike가 아닌)가되도록 선택할 수 있습니다 :

class HumanLike implements Forgiver {
    void forgive() {
       // forgive but remember    
    }
}

또는 신처럼되고 다음과 같이 할 수 있습니다.

class AngelLike extends GodLike {
    void forget() {
       // forget to forgive     
    }
}

자바 8 인터페이스를 가진 PS 는 또한 정적 (재정의 가능한 구현) 메소드뿐만 아니라 정적 b / w 인터페이스와 추상 클래스의 차이가 더 좁아 질 수 있습니다.


1

거의 모든 것이 여기에서 이미 다루고있는 것 같다 abstract.

abstract키워드는 클래스가 인스턴스화되는 것을 막기 위해서도 사용됩니다. 인스턴스화하고 싶지 않은 구체적인 클래스가있는 경우-확인하십시오 abstract.


1

흠 이제 사람들은 굶주린 실용적인 접근 방식입니다, 당신은 꽤 맞습니다. 그러나 대부분의 면접관은 현재의 요구 사항에 따라 보이며 실용적인 접근 방식을 원합니다.

답을 마치면 예제로 넘어 가야합니다.

요약:

예를 들어, 우리는 모든 직원에게 공통적 인 매개 변수를 가진 급여 기능을 가지고 있습니다. 그런 다음 부분적으로 정의 된 메소드 본문을 가진 CTC라는 추상 클래스를 가질 수 있으며 모든 유형의 직원에 의해 확장되고 추가 혜택에 따라 재정의됩니다. 일반적인 기능성.

public abstract class CTC {

    public int salary(int hra, int da, int extra)
    {
        int total;
        total = hra+da+extra;
        //incentive for specific performing employee
        //total = hra+da+extra+incentive;
        return total;
    }
}

class Manger extends CTC
{
}


class CEO extends CTC
{
}

class Developer extends CTC
{   
}

상호 작용

java의 interface는 interfcae 기능을 확장하지 않고도 사용할 수 있으며 응용 프로그램에 도입하려는 기능의 서명을 구현해야합니다. 그것은 당신에게 정의를 강요 할 것입니다. 다른 기능.

public interface EmployeType {

    public String typeOfEmployee();
}

class ContarctOne implements EmployeType
{

    @Override
    public String typeOfEmployee() {
        return "contract";
    }

}

class PermanentOne implements EmployeType
{

    @Override
    public String typeOfEmployee() {
        return "permanent";
    }

}

당신은 정의 된 methgos에 의해 추상 클래스로 추상 클래스와 같은 강제 활동을 추상 클래스로 가질 수 있습니다.


1

내가 이해하고 접근하는 방식에서

인터페이스는 사양 / 계약과 같습니다. 인터페이스 클래스를 구현하는 모든 클래스는 추상 클래스에 정의 된 모든 메소드를 구현해야합니다 (기본 메소드 제외 (Java 8에 도입)).

클래스의 일부 메소드와 일부 메소드에 필요한 구현을 알면 클래스 요약을 정의하는 동안 여전히 구현이 무엇인지 알지 못합니다 (함수 서명은 알 수 있지만 구현은 알 수 없음). 이 메소드를 구현하는 방법을 알면 나중에 개발 부분에서이 추상 클래스를 확장하고 메소드를 구현할 수 있습니다.

참고 : 메소드가 정적 또는 기본값이 아닌 경우 인터페이스 메소드에 함수 본문을 가질 수 없습니다.


0

면접관이 얻으려고했던 것은 아마도 인터페이스와 구현의 차이 일 것이라고 생각합니다.

코드 모듈에 대한 인터페이스 (자바 인터페이스는 아니지만보다 일반적인 용어로 "인터페이스")는 기본적으로 인터페이스를 사용하는 클라이언트 코드와의 계약입니다.

코드 모듈의 구현은 모듈을 작동시키는 내부 코드입니다. 종종 하나 이상의 다른 방식으로 특정 인터페이스를 구현할 수 있으며, 변경 사항을 인식하지 않고도 클라이언트 코드없이 구현을 변경할 수도 있습니다.

Java 인터페이스는 구현을 지정하지 않고 클래스를 사용하여 클라이언트 코드의 이점을 위해 클래스가 작동하는 방식을 정의하기 위해 위의 일반적인 의미로 인터페이스로만 사용해야합니다. 따라서 인터페이스에는 클라이언트 코드에 의해 호출 될 것으로 예상되는 메소드에 대한 메소드 서명 (이름, 리턴 유형 및 인수 목록)이 포함되며 원칙적으로 해당 메소드가 수행하는 작업을 설명하는 각 메소드마다 많은 Javadoc이 있어야합니다. 인터페이스를 사용하는 가장 매력적인 이유는 여러 가지 다른 인터페이스 구현을 계획하고 있다면 배치 구성에 따라 구현을 선택할 수 있기 때문입니다.

이와 대조적으로 Java 추상 클래스는 인터페이스를 지정하는 기본 목적 대신 클래스의 부분 구현을 제공합니다. 여러 클래스가 코드를 공유 할 때 사용해야하지만 서브 클래스가 구현의 일부를 제공해야하는 경우에도 사용해야합니다. 이를 통해 공유 코드가 추상 클래스 인 한 곳에만 표시 될 수 있지만 구현의 일부가 추상 클래스에없고 서브 클래스에 의해 제공 될 것으로 예상됩니다.


0

귀하의 답변은 맞지만 면접관은 Java의 세부 사항이 아닌 소프트웨어 엔지니어링 관점에 따라 차별화해야합니다.

간단한 단어 :

인터페이스는 상점의 인터페이스와 유사하지만 상점에 표시되어야하는 모든 것이 있으므로 인터페이스의 모든 메소드는 구체적 클래스에서 구현되어야합니다. 이제 일부 클래스가 정확한 메소드를 공유하고 다른 클래스가 다른 경우 어떻게해야합니까? 인터페이스가 두 가지를 포함하는 상점에 관한 것이라고 가정하고, 두 개의 상점에 모두 스포츠 장비가 포함되어 있지만 한 옷에는 여분의 옷이 있고 다른 옷에는 여분의 신발이 있다고 가정하십시오. 그래서 당신이하는 일은 Sports 메소드를 구현하고 다른 메소드를 구현하지 않은 Sport에 대한 추상 클래스를 만드는 것입니다. 여기서 추상 클래스는이 상점 자체가 존재하지 않지만 다른 클래스 / 숍의 기반이라는 의미입니다. 이렇게하면 코드를 구성하고 코드 복제 오류를 방지하고 코드를 통합하며 다른 클래스의 재사용 성을 보장 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.