Constructor en una Interfaz?


Sé que no es posible definir un constructor en una interfaz. Pero me pregunto por qué, porque creo que podría ser muy útil.

Así que puede estar seguro de que algunos campos de una clase están definidos para cada implementación de esta interfaz.

Por ejemplo, considere la siguiente clase de mensaje:

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

Si a define una interfaz para esta clase para que pueda tener más clases que implementen la interfaz de mensaje, solo puedo definir el método send y no el constructor. Entonces, ¿cómo puedo asegurar que cada implementación de esta clase realmente tenga un conjunto de receptores? Si utilizo un método como setReceiver(String receiver) no puedo estar seguro de que este método sea realmente llamado. En el constructor pude asegurarlo.

Author: daniel kullmann, 2010-05-10

11 answers

Tomando algunas de las cosas que has descrito:

" Así que puede estar seguro de que algunos campos de una clase están definidos para cada implementación de esta interfaz."

" Si a definir una interfaz para esta clase para que pueda tener más clases que implementan la interfaz de mensajes, solo puedo definir la enviar método y no el constructor"

...estos requisitos son exactamente para lo que son las clases abstractas.

 118
Author: matt b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-08 13:41:48

Un problema que se presenta cuando se permiten constructores en interfaces viene de la posibilidad de implementar varias interfaces al mismo tiempo. Cuando una clase implementa varias interfaces que definen diferentes constructores, la clase tendría que implementar varios constructores, cada uno satisfaciendo solo una interfaz, pero no las otras. Será imposible construir un objeto que llama a cada uno de estos constructores.

O en código:

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); 
  }
}
 64
Author: daniel kullmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-19 09:16:13

Una interfaz define un contrato para una API, es decir, un conjunto de métodos que tanto el implementador como el usuario de la API acuerdan. Una interfaz no tiene una implementación instanciada, por lo tanto no tiene constructor.

El caso de uso que describe es similar a una clase abstracta en la que el constructor llama a un método de un método abstracto que se implementa en una clase hija.

El problema inherente aquí es que mientras se ejecuta el constructor base, el objeto hijo no construido todavía, y por lo tanto en un estado impredecible.

Para resumir: ¿está buscando problemas cuando llama a métodos sobrecargados de constructores padres, para citar mindprod :

En general, debe evitar llamar a cualquier métodos no finales en un constructor. El problema es esa instancia inicializadores / inicialización de variables en la clase derivada se realiza después de el constructor de la base clase.

 10
Author: rsp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-10 15:50:51

Solo hay campos estáticos en la interfaz que no necesitan inicializarse durante la creación de objetos en la subclase y el método de interfaz tiene que proporcionar una implementación real en la subclase .

Segunda razón-durante la creación del objeto de la subclase, se llama al constructor padre .Pero si habrá más de una interfaz implementada, se producirá un conflicto durante la llamada del constructor de interfaz en cuanto a qué interfaz constructor llamará primero

 4
Author: Satyajit Gami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-30 09:25:46

Las dependencias a las que no se hace referencia en los métodos de una interfaz deben considerarse detalles de implementación, no algo que la interfaz impone. Por supuesto, puede haber excepciones, pero como regla general, debe definir su interfaz como lo que se espera que sea el comportamiento. El estado interno de una implementación dada no debería ser una preocupación de diseño de la interfaz.

 2
Author: Yishai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-10 15:44:12

Una solución que puede intentar es definir un método getInstance() en su interfaz para que el implementador sea consciente de qué parámetros deben manejarse. No es tan sólido como una clase abstracta, pero permite más flexibilidad al ser una interfaz.

Sin embargo, esta solución requiere que use getInstance() para crear instancias de todos los objetos de esta interfaz.

Por ejemplo

public interface Module {
    Module getInstance(Receiver receiver);
}
 2
Author: Lappro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-03 13:40:04

Ver esta preguntapara el por qué (tomado de los comentarios).

Si realmente necesita hacer algo como esto, es posible que desee una clase base abstracta en lugar de una interfaz.

 1
Author: JSBձոգչ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:27

Esto se debe a que las interfaces no permiten definir el cuerpo del método en él.pero deberíamos tener que definir el constructor en la misma clase que las interfaces tienen por defecto el modificador abstracto para todos los métodos a definir. Es por eso que no podemos definir constructor en las interfaces.

 1
Author: Aasif Ali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-12 05:13:42

Si desea asegurarse de que cada implementación de la interfaz contiene un campo específico, simplemente necesita agregar a su interfaz el getter para ese campo :

interface IMyMessage(){
    @NonNull String getReceiver();
}
  • no romperá la encapsulación
  • hará saber a todos los que usan su interfaz que el objeto Receiver tiene que ser pasado a la clase de alguna manera (ya sea por constructor o por setter)
 1
Author: Denys Vasylenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-15 13:37:25

He aquí un ejemplo usando esta Técnica. En este ejemplo específico el código está haciendo una llamada a Firebase usando un mock MyCompletionListener que es una interfaz enmascarada como una clase abstracta, una interfaz con un 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);
}
 0
Author: Erik Hellberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-09 20:50:56

Generalmente los constructores son para inicializar miembros no estáticos de una clase particular con respecto a un objeto.

No hay creación de objetos para interface ya que solo hay métodos declarados pero no métodos definidos. La razón por la que no podemos crear objetos para métodos declarados es que la creación de objetos no es más que asignar algo de memoria (en memoria de montón) para miembros no estáticos.

JVM creará memoria para los miembros que están completamente desarrollados y listos para usar.Sobre la base de esos miembros , JVM calcula la cantidad de memoria necesaria para ellos y crea memoria.

En caso de métodos declarados, JVM no puede calcular la cantidad de memoria requerida para estos métodos declarados, ya que la implementación será en el futuro, lo que no se realiza en este momento. por lo tanto, la creación de objetos no es posible para interface.

Conclusión:

Sin la creación de objetos, no hay posibilidad de inicializar miembros no estáticos a través de un constructor.Es por eso que constructor no está permitido dentro de un interfaz.(como no hay uso de constructor dentro de una interfaz)

 0
Author: Sai Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-30 10:24:03