java interface - Constructor en una interfaz?




usage abstract (10)

Si desea asegurarse de que cada implementación de la interfaz contenga 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 se debe pasar a la clase de alguna manera (ya sea por constructor o por instalador)

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

Por lo tanto, puede estar seguro de que se definen algunos campos en una clase 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 defino una interfaz para esta clase para poder tener más clases que implementen la interfaz del mensaje, solo puedo definir el método de envío y no el constructor. Entonces, ¿cómo puedo asegurarme de que cada implementación de esta clase realmente tenga un receptor configurado? Si utilizo un método como setReceiver(String receiver) no puedo estar seguro de que se llame realmente este método. En el constructor podría asegurarlo.


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

No hay creación de objetos para la interfaz, ya que solo hay métodos declarados pero no definidos. Por qué no podemos crear un objeto para los métodos declarados La creación de un objeto is no es otra cosa que la asignación de cierta memoria (en la memoria del montón) para miembros no estáticos.

JVM creará memoria para los miembros que están completamente desarrollados y listos para usar. De acuerdo con esos miembros, JVM calcula cuánta memoria se requiere para ellos y crea memoria.

En el caso de los métodos declarados, JVM no puede calcular la cantidad de memoria necesaria para estos métodos declarados, ya que la implementación será en el futuro, lo que no está hecho en este momento. por lo que la creación de objetos no es posible para la interfaz.

conclusión:

sin creación de objetos, no hay posibilidad de inicializar miembros no estáticos a través de un constructor. Es por eso que el constructor no está permitido dentro de una interfaz (ya que no se usa el constructor dentro de una interfaz)


Un problema que obtienes al permitir constructores en las interfaces proviene 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 llame a cada uno de estos constructores.

O en el 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); 
  }
}

Un trabajo que puede intentar es definir un método getInstance() en su interfaz para que el implementador sepa qué parámetros deben manejarse. No es tan sólido como una clase abstracta, pero permite una mayor flexibilidad como interfaz.

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

P.ej

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

Solo hay campos estáticos en la interfaz que no necesitan inicializarse durante la creación del objeto en la subclase y el método de la interfaz debe proporcionar la implementación real en la subclase. Por lo tanto, no es necesario el constructor en la interfaz.

Segundo motivo: durante la creación del objeto de la subclase, se llama al constructor padre. Pero si hay más de una interfaz implementada, se producirá un conflicto durante la llamada del constructor de la interfaz en cuanto al constructor de la interfaz que llamará primero


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


Una interfaz define un contrato para una API, que es un conjunto de métodos que acuerdan tanto el implementador como el usuario de la API. Una interfaz no tiene una implementación instanciada, por lo tanto no hay 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 secundaria.

El problema inherente aquí es que mientras el constructor base se está ejecutando, el objeto hijo no está construido aún, y por lo tanto en un estado impredecible.

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

En general, debe evitar llamar a cualquier método no final en un constructor. El problema es que la inicialización de instancias / inicialización de variable en la clase derivada se realiza después del constructor de la clase base.


Tomando algunas de las cosas que has descrito:

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

"Si a definir una interfaz para esta clase para que pueda tener más clases que implementen la interfaz del mensaje, solo puedo definir el método de envío y no el constructor"

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


Vea esta pregunta por 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.


Como ya habrán conseguido los conocimientos teóricos de los expertos, no estoy pasando mucho en repetir palabras a todos aquellos que aquí, en lugar permítanme explicar con un ejemplo sencillo en el que podemos usar / no se puede utilizar Interfacey Abstract class.

Tenga en cuenta que está diseñando una aplicación para enumerar todas las características de Cars. En varios puntos necesita herencia en común, ya que algunas de las propiedades como DigitalFuelMeter, Aire Acondicionado, ajuste de Asiento, etc. son comunes para todos los autos. Del mismo modo, necesitamos herencia para algunas clases solo, ya que algunas de las propiedades como el Sistema de frenado (ABS, EBD) son aplicables solo para algunos autos.

La siguiente clase actúa como una clase base para todos los autos:

public class Cars
{
    public string DigitalFuelMeter()
    {
        return "I have DigitalFuelMeter";
    }

    public string AirCondition()
    {
        return "I have AC";
    }

    public string SeatAdjust()
    {
        return "I can Adjust seat";
    }
}

Tenga en cuenta que tenemos una clase separada para cada coches.

public class Alto : Cars
{
    // Have all the features of Car class    
}

public class Verna : Cars
{
    // Have all the features of Car class + Car need to inherit ABS as the Braking technology feature which is not in Cars        
}

public class Cruze : Cars
{
    // Have all the features of Car class + Car need to inherit EBD as the Braking technology feature which is not in Cars        
}

Considere que necesitamos un método para heredar la tecnología de frenado para los autos Verna y Cruze (no aplicable para Alto). Aunque ambos usan tecnología de frenado, la "tecnología" es diferente. Así que estamos creando una clase abstracta en la que el método se declarará como abstracto y se debe implementar en sus clases secundarias.

public abstract class Brake
{
    public abstract string GetBrakeTechnology();
}

Ahora estamos tratando de heredar de esta clase abstracta y el tipo de sistema de frenos se implementa en Verna y Cruze:

public class Verna : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }       
}

public class Cruze : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
       return "I use EBD system for braking";
    }         
}

¿Ves el problema en las dos clases anteriores? Heredan de varias clases que C # .Net no permite incluso si el método se implementa en los hijos. Aquí viene la necesidad de la interfaz.

interface IBrakeTechnology
{
    string GetBrakeTechnology();
}

Y la implementación se da a continuación:

public class Verna : Cars, IBrakeTechnology
{
    public string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }
}

public class Cruze : Cars, IBrakeTechnology
{
   public string GetBrakeTechnology()
   {
       return "I use EBD system for braking";
   }        
}

Ahora, Verna y Cruze pueden lograr múltiples herencias con su propio tipo de tecnologías de frenado con la ayuda de Interface.





java interface