Pautas de uso de la Interfaz Java - ¿Son malos los getters y setters en una interfaz?


¿Qué piensan las personas de las mejores pautas para usar en una interfaz? ¿Qué debería y qué no debería entrar en una interfaz?

He escuchado a la gente decir que, como regla general, una interfaz solo debe definir el comportamiento y no el estado. ¿Significa esto que una interfaz no debería contener getters y setters?

Mi opinión: Tal vez no sea así para los setters, pero a veces creo que los getters son válidos para ser colocados en una interfaz. Esto es simplemente para hacer cumplir las clases de implementación para implementar esos getters y así indicar que los clientes son capaces de llamar a esos getters para comprobar algo, por ejemplo.

Author: oxbow_lakes, 2009-07-15

11 answers

Creo que hay dos tipos de interfaces declaradas en general:

  1. a descripción del servicio. Esto podría ser algo así como CalculationService. No creo que los métodos getX debe ser en este tipo de interfaz, y ciertamente no setX. Claramente implican detalles de implementación, que no es el trabajo de este tipo de interfaz.
  2. a data model - existe únicamente para abstraer la implementación de objetos de datos en el sistema. Estos podrían ser se usa para ayudar en las pruebas o simplemente porque algunas personas tan viejas como yo recuerdan los días en que (por ejemplo) el uso de un marco de persistencia lo ataba a tener una superclase en particular (es decir, elegiría implementar una interfaz en caso de que cambiara su capa de persistencia). Creo que tener métodos JavaBean en este tipo de interfaz es totalmente razonable.

Nota: las clases de colecciones probablemente encajan para escribir #2

 12
Author: oxbow_lakes,
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
2009-07-15 09:58:43

No veo por qué una interfaz no puede definir getters y setters. Por ejemplo, List.size() es efectivamente un captador. Sin embargo, la interfaz debe definir el comportamiento en lugar de la implementación - no puede decir cómo manejarás el estado, pero puede insistir en que puedas obtenerlo y configurarlo.

Las interfaces de colección tienen que ver con el estado, por ejemplo, pero diferentes colecciones pueden almacenar ese estado de maneras radicalmente diferentes.

EDITAR: Los comentarios sugieren que getters y setters implican que se utiliza un campo simple para el almacenamiento de respaldo. Estoy vehementemente en desacuerdo con esta implicación. En mi opinión, hay una implicación de que es "razonablemente barato" para obtener/establecer el valor, pero no que se almacena como un campo con una implementación trivial.


EDITAR: Como se indica en los comentarios, esto se hace explícito en la especificación JavaBeans sección 7.1:

Por Lo tanto, incluso cuando un guionista tipos en algo como b.Label = foo hay todavía una llamada de método en el objeto de destino para establecer la propiedad, y el objeto de destino tiene completo control programático.

Así que las propiedades no tienen que ser simples campos de datos, que en realidad pueden ser valores calculados. Las actualizaciones pueden tener varios efectos secundarios programáticos. Para ejemplo, cambiar el fondo de un frijol la propiedad color también puede causar bean para ser repintado con el nuevo color."


Si la supuesta implicación fuera verdadera, podríamos tan bien exponer propiedades como campos directamente. Afortunadamente esa implicación no se sostiene: los getters y setters están perfectamente dentro de sus derechos para calcular las cosas.

Por ejemplo, considere un componente con

getWidth()
getHeight()
getSize()

¿Cree que hay una implicación de que hay tres variables allí? ¿No sería razonable tener:

private int width;
private int height;

public int getWidth() {
    return width;
}

public int getHeight() {
    return height;
}

public Size getSize() {
    return new Size(width, height); // Assuming an immutable Size type
}

O (preferentemente IMO):

private Size size;

public int getWidth() {
    return size.getWidth();
}

public int getHeight() {
    return size.getHeight();
}

public Size getSize() {
    return size;
}

Aquí, la propiedad size o las propiedades height / width son para solo conveniencia, pero no veo que eso los haga inválidos de ninguna manera.

 24
Author: Jon Skeet,
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
2009-07-15 10:42:55

No hay nada inherentemente malo en los getters/setters. Sin embargo:

  1. Tiendo a hacer mis objetos inmutables (en primera instancia) con respecto a los campos que contienen. ¿Por qué? Instancio la mayoría de las cosas durante la fase de construcción. Si quiero cambiar algo más tarde, entonces relajo esas restricciones. Así que mis interfaces tenderán a contener getters, pero no setters (hay otros beneficios - particularmente threading).
  2. Quiero que mis objetos hagan cosas por mí , no al revés. Así que cuando uno de mis objetos adquiere una serie de captadores, empiezo a preguntar si ese objeto debería tener más funcionalidad en él, en lugar de exponer todos sus datos para otra cosa con la que trabajar. Vea esta respuesta para más detalles.

Estas son todas las directrices, nota.

 10
Author: Brian Agnew,
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 12:01:54

No creo que un bean deba tener una interfaz encima, en general. Un javabean es una interfaz en el sentido más general. Una Interfaz especifica el contrato externo de algo más complejo. El contrato externo de un javabean y su representación interna son idénticos.

No diría que no deberías tener getters en una interfaz, sin embargo. Tiene mucho sentido tener una interfaz ReadableDataThingie implementada por DataThingieBean.

 4
Author: Kevin Peterson,
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
2009-07-15 09:19:40

He oído a la gente decir que, como un regla general, una interfaz solo debe define el comportamiento y no el estado. Hacer esto significa que una interfaz no contener getters y setters?

Para empezar, al menos con Java y excluyendo declaraciones de excepción, no se puede definir un comportamiento completo sin estado. En Java, las interfaces no definen el comportamiento. Lo que definen son tipos; promesas de implementar un conjunto de firmas de características posiblemente con algunos post-condiciones wrt excepciones. Pero eso es todo. El comportamiento y el estado están definidos por las clases que implementan esas interfaces.

En segundo lugar, si los getters y setters están definidos en una interfaz, realmente no definen el comportamiento completo (otro que uno es para read y otro para write wrt a property.) Puede tener un comportamiento complejo detrás de los setters y getters, pero solo se pueden implementar en las clases reales. No hay nada en el lenguaje Java que nos permita definir libremente el comportamiento en interfaces excepto en los casos más restrictivos.

Con eso en consideración, no hay nada malo - sintácticamente y semánticamente - con tener setters y getters en interfaces.

Si su aplicación está bien modelada y el problema requiere que tenga una interfaz que defina setters y getters, por qué no. Por ejemplo, eche un vistazo a la interfaz ServletResponse.

Ahora, si nos fijamos en getters y setters desde el punto de vista de implementando clases compatibles con las especificaciones de JavaBeans, entonces no necesita definir interfaces para ellas.

Pero si tiene cosas que requieren setters y getters, como un bean might, y que también se requiere que se conecten al tipo de compilación (no en tiempo de ejecución como un bean might), y para las que pueden existir múltiples implementaciones, entonces sí, esto requeriría una interfaz que defina getters y setters.

Espero que ayude.

 2
Author: luis.espinal,
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-04-03 22:24:54

Esto toca todo el tema Getter/Setters are evil que se aborda varias veces en este sitio y en otros lugares.

Tiendo a preferir no tener accesores en la interfaz, sino agregar colaboradores usando argumentos de constructor a la implementación.

 1
Author: Paul McKenzie,
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
2009-07-15 09:25:10

El hecho de que la implementación directa de algo sea como un getter no debería impedir que esté en una interfaz si es necesario.

 1
Author: soru,
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
2009-07-15 09:32:24

Para más información: Confesiones prácticas de Diseño de API de un Arquitecto de Marco de Java (Jaroslav Tulach, 2008, Apress).

 0
Author: akarnokd,
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
2009-07-15 09:24:46

Utilicé ese tipo de interfaces, por ejemplo, teníamos clases con campos beginDate, endDate. Esos campos estaban en muchas clases y tenía un caso de uso que necesito para obtener esas fechas para diferentes objetos, así que extraje la interfaz y estaba muy feliz:)

 0
Author: IAdapter,
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
2009-07-15 10:24:37

Básicamente si la respuesta a "¿Necesito saber el valor de [state, property, whateverThignAMaGit] para trabajar con una instancia de la misma ?"entonces sí... los accesores pertenecen a la interfaz.

Lista.size () de John es un ejemplo perfecto de un getter que necesita ser definido en una interfaz

 0
Author: Newtopian,
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
2009-07-15 10:26:07

Los getters se utilizan para consultar el estado de un objeto, lo que realmente puede evitar al diseñar su interfaz. Leer http://www.pragprog.com/articles/tell-dont-ask

 0
Author: ,
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
2009-08-16 19:01:13