Programming

인터페이스의 생성자?

procodes 2020. 6. 23. 08:06
반응형

인터페이스의 생성자?


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

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

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

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); 
  }
}

An interface defines a contract for an API, that is a set of methods that both implementer and user of the API agree upon. An interface does not have an instanced implementation, hence no constructor.

The use case you describe is akin to an abstract class in which the constructor calls a method of an abstract method which is implemented in an child class.

The inherent problem here is that while the base constructor is being executed, the child object is not constructed yet, and therfore in an unpredictable state.

To summarize: is it asking for trouble when you call overloaded methods from parent constructors, to quote mindprod:

In general you must avoid calling any non-final methods in a constructor. The problem is that instance initialisers / variable initialisation in the derived class is performed after the constructor of the base class.


There is only static fields in interface that dosen't need to initialized during object creation in subclass and the method of interface has to provide actual implementation in subclass .So there is no need of constructor in interface.

Second reason-during the object creation of subclass, the parent constructor is called .But if there will be more than one interface implemented then a conflict will occur during call of interface constructor as to which interface's constructor will call first


A work around you can try is defining a getInstance() method in your interface so the implementer is aware of what parameters need to be handled. It isn't as solid as an abstract class, but it allows more flexibility as being an interface.

However this workaround does require you to use the getInstance() to instantiate all objects of this interface.

E.g.

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

Dependencies that are not referenced in an interfaces methods should be regarded as implementation details, not something that the interface enforces. Of course there can be exceptions, but as a rule, you should define your interface as what the behavior is expected to be. Internal state of a given implementation shouldn't be a design concern of the interface.


If you want to make sure that every implementation of the interface contains specific field, you simply need to add to your interface the getter for that field:

interface IMyMessage(){
    @NonNull String getReceiver();
}
  • it won't break encapsulation
  • it will let know to everyone who use your interface that the Receiver object has to be passed to the class in some way (either by constructor or by setter)

See this question for the why (taken from the comments).

If you really need to do something like this, you may want an abstract base class rather than an interface.


This is because interfaces do not allow to define the method body in it.but we should have to define the constructor in the same class as interfaces have by default abstract modifier for all the methods to define. That's why we can not define constructor in the interfaces.


Here´s an example using this Technic. In this specifik example the code is making a call to Firebase using a mock MyCompletionListener that is an interface masked as an abstract class, an interface with a constructor

private interface Listener {
    void onComplete(databaseError, databaseReference);
}

public abstract class MyCompletionListener implements Listener{
    String id;
    String name;
    public MyCompletionListener(String id, String name) {
        this.id = id;
        this.name = name;
    }
}

private void removeUserPresenceOnCurrentItem() {
    mFirebase.removeValue(child("some_key"), new MyCompletionListener(UUID.randomUUID().toString(), "removeUserPresenceOnCurrentItem") {
        @Override
        public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {

        }
    });
    }
}

@Override
public void removeValue(DatabaseReference ref, final MyCompletionListener var1) {
    CompletionListener cListener = new CompletionListener() {
                @Override
                public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
                    if (var1 != null){
                        System.out.println("Im back and my id is: " var1.is + " and my name is: " var1.name);
                        var1.onComplete(databaseError, databaseReference);
                    }
                }
            };
    ref.removeValue(cListener);
}

Generally constructors are for initializing non-static members of particular class with respect to object.

There is no object creation for interface as there is only declared methods but not defined methods. Why we can’t create object to declared methods is-object creation is nothing but allocating some memory (in heap memory) for non-static members.

JVM will create memory for members which are fully developed and ready to use.Based on those members , JVM calculates how much of memory required for them and creates memory.

Incase of declared methods, JVM is unable to calculate the how much memory will required to these declared methods as the implementation will be in future which is not done by this time. so object creation is not possible for interface.

conclusion:

without object creation, there is no chance to initialize non-static members through a constructor.That is why constructor is not allowed inside a interface.(as there is no use of constructor inside a interface)

참고URL : https://stackoverflow.com/questions/2804041/constructor-in-an-interface

반응형