[java] 인터페이스의 생성자?

인터페이스에서 생성자를 정의 할 수 없다는 것을 알고 있습니다. 그러나 나는 그것이 매우 유용 할 수 있다고 생각하기 때문에 이유가 궁금합니다.

따라서 클래스의 일부 필드가이 인터페이스의 모든 구현에 대해 정의되어 있는지 확인할 수 있습니다.

예를 들어 다음 메시지 클래스를 고려하십시오.

public class MyMessage {

   public MyMessage(String receiver) {
      this.receiver = receiver;
   }

   private String receiver;

   public void send() {
      //some implementation for sending the mssage to the receiver
   }
}

메시지 인터페이스를 구현하는 더 많은 클래스를 가질 수 있도록이 클래스에 대한 인터페이스를 정의하면 생성자가 아닌 send 메소드 만 정의 할 수 있습니다. 그렇다면이 클래스의 모든 구현에 실제로 수신기 세트가 있는지 어떻게 확인할 수 있습니까? 같은 방법을 사용하면 setReceiver(String receiver)이 방법이 실제로 호출되는지 확신 할 수 없습니다. 생성자에서 확인할 수 있습니다.



답변

당신이 묘사 한 것들 중 일부를 취하는 것 :

“따라서 클래스의 일부 필드가이 인터페이스의 모든 구현에 대해 정의되어 있는지 확인할 수 있습니다.”

“메시지 인터페이스를 구현하는 더 많은 클래스를 가질 수 있도록이 클래스에 대한 인터페이스를 정의하면 생성자가 아닌 send 메소드 만 정의 할 수 있습니다.”

…이 요구 사항은 정확히 추상 클래스 에 대한 것입니다.


답변

인터페이스에서 생성자를 허용하면 여러 인터페이스를 동시에 구현할 수 있다는 문제가 발생합니다. 클래스가 다른 생성자를 정의하는 여러 인터페이스를 구현할 때 클래스는 여러 생성자를 구현해야합니다. 각 생성자는 하나의 인터페이스 만 만족하지만 다른 인터페이스는 만족하지 않습니다. 이러한 각 생성자를 호출하는 객체를 생성하는 것은 불가능합니다.

또는 코드에서 :

interface Named { Named(String name); }
interface HasList { HasList(List list); }

class A implements Named, HasList {

  /** implements Named constructor.
   * This constructor should not be used from outside, 
   * because List parameter is missing
   */
  public A(String name)  { 
    ...
  }

  /** implements HasList constructor.
   * This constructor should not be used from outside, 
   * because String parameter is missing
   */
  public A(List list) {
    ...
  }

  /** This is the constructor that we would actually 
   * need to satisfy both interfaces at the same time
   */ 
  public A(String name, List list) {
    this(name);
    // the next line is illegal; you can only call one other super constructor
    this(list); 
  }
}


답변

인터페이스는 API의 계약자, 즉 API의 구현 자와 사용자가 동의하는 메소드 세트를 정의합니다. 인터페이스에는 인스턴스화 된 구현이 없으므로 생성자가 없습니다.

설명하는 사용 사례는 생성자가 자식 클래스에서 구현되는 추상 메서드의 메서드를 호출하는 추상 클래스와 유사합니다.

여기서 기본 문제는 기본 생성자가 실행되는 동안 자식 개체가 아직 구성되지 않았으므로 예측할 수없는 상태라는 것입니다.

요약 : mindprod 를 인용하기 위해 부모 생성자에서 오버로드 된 메소드를 호출 할 때 문제가 발생 합니까 ?

일반적으로 생성자에서 최종이 아닌 메소드를 호출하지 않아야합니다. 문제는 파생 클래스의 인스턴스 이니셜 라이저 / 변수 초기화 가 기본 클래스의 생성자 후에 수행된다는 것
입니다.


답변

해결 getInstance()방법은 인터페이스에서 메소드를 정의 하여 구현자가 처리해야하는 매개 변수를 인식하는 것입니다. 추상 클래스만큼 견고하지는 않지만 인터페이스보다 유연성이 뛰어납니다.

그러나이 해결 방법을 사용하려면 getInstance()이 인터페이스의 모든 객체를 인스턴스화 하기 위해를 사용해야합니다 .

예 :

public interface Module {
    Module getInstance(Receiver receiver);
}


답변

인터페이스에는 서브 클래스에서 객체를 생성하는 동안 초기화 할 필요가없는 정적 필드 만 있으며 인터페이스의 메소드는 서브 클래스에서 실제 구현을 제공해야하므로 인터페이스에는 생성자가 필요하지 않습니다.

두 번째 이유는 서브 클래스의 객체 생성 중에 부모 생성자를 호출합니다. 그러나 둘 이상의 인터페이스가 구현 된 경우 인터페이스 생성자를 호출하는 동안 어떤 인터페이스의 생성자가 먼저 호출하는지에 대한 충돌이 발생합니다.


답변

인터페이스의 모든 구현에 특정 필드가 포함되도록하려면 해당 필드 의 getter를 인터페이스에 추가하면됩니다 .

interface IMyMessage(){
    @NonNull String getReceiver();
}
  • 캡슐화가 깨지지 않습니다.
  • 인터페이스를 사용하는 모든 사람에게 Receiver객체가 어떤 식 으로든 클래스에 전달되어야 한다는 것을 알 수 있습니다 (생성자 또는 설정자에 의해)

답변

인터페이스 메소드에서 참조되지 않은 종속성은 인터페이스가 강제하는 것이 아니라 구현 세부 사항으로 간주되어야합니다. 물론 예외가있을 수 있지만 일반적으로 인터페이스가 동작이 예상되는대로 정의해야합니다. 주어진 구현의 내부 상태는 인터페이스의 디자인 문제가되어서는 안됩니다.