Del libro Effective Java por Joshua Bloch
artículo 19: Use sólo las interfaces para definir tipos
Cuando una clase implementa una interfaz, la interfaz sirve como un tipo que puede ser usado para referirse a instancias de la clase. Que una clase implemente una interfaz debería decir algo acerca de lo que un cliente puede hacer con las instancias de la clase . No es apropiado definir una interfaz para ningún otro propósito.
Un tipo de interfaz que no supera esta prueba es la llamada interfaz constante. Tal interfaz no contiene ningún método; consiste únicamente en campos finales estáticos, cada exportando una constante. Las clases que usan estas constantes implementan la interfaz a evitan la necesidad de calificar nombres constantes con un nombre de clase. Este es un ejemplo:
// Constant interface antipattern - do not use!
public interface PhysicalConstants {
// Avogadro's number (1/mol)
static final double AVOGADROS_NUMBER = 6.02214199e23;
// Boltzmann constant (J/K)
static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
// Mass of the electron (kg)
static final double ELECTRON_MASS = 9.10938188e-31;
}
El patrón de interfaz constante es un mal uso de interfaces. Que una clase use algunas constantes internamente es un detalle de implementación. Implementar una interfaz constante hace que este detalle de implementación se filtre en la API exportada de la clase. Es no tiene ninguna consecuencia para los usuarios de una clase que la clase implementa una interfaz constante . De hecho, incluso puede confundirlos. Peor aún, representa un compromiso: si en una versión futura la clase se modifica para que ya no necesite usar las constantes, aún debe implementar la interfaz para garantizar la compatibilidad binaria. Si una clase no final implementa una interfaz constante, todas sus subclases tendrán sus espacios de nombres contaminados por las constantes en la interfaz.
Hay varias interfaces constantes en las bibliotecas de la plataforma Java, como java.io.ObjectStreamConstants. Estas interfaces deben considerarse anomalías y no deben emularse.
Si desea exportar constantes, hay varias opciones razonables. Si las constantes están estrechamente vinculadas a una clase o interfaz existente, debe agregarlas a la clase o interfaz. Por ejemplo, todas las clases primitivas numéricas encuadradas, , como Integer y Double, exportan constantes MIN_VALUE y MAX_VALUE. Si las constantes se ven mejor como miembros de un tipo enumerado, debe exportarlos con un tipo de enumeración (Ítem 30). De lo contrario, debe exportar las constantes con una clase de utilidad no instalable (Artículo 4). Aquí está una versión de la clase utilidad del ejemplo anterior PhysicalConstants:
// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
private PhysicalConstants() {
} // Prevents instantiation
public static final double AVOGADROS_NUMBER = 6.02214199e23;
public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
public static final double ELECTRON_MASS = 9.10938188e-31;
}
Normalmente una clase de utilidad requiere que los clientes para calificar nombres constantes con un nombre de clase , por ejemplo, PhysicalConstants.AVOGADROS_NUMBER. Si realiza un uso pesado de de las constantes exportadas por una clase de utilidad, puede evitar la necesidad de calificar las constantes con el nombre de clase haciendo uso de la instalación de importación estática, presentada en la versión 1.5:
// Use of static import to avoid qualifying constants
import static com.effectivejava.science.PhysicalConstants.*;
public class Test {
double atoms(double mols) {
return AVOGADROS_NUMBER * mols;
}
...
// Many more uses of PhysicalConstants justify static import
}
En resumen, las interfaces deben utilizarse sólo para definir tipos. No deberían usarse para exportar constantes.
Puede hacer variables de tipo interfaz si la interfaz es implementada por la clase? He leído que esta es una mejor manera de crear una variable en una clase porque si agrega nuevos métodos no tiene que cambiar cada instancia de la variable en la clase. clase A implementar Binterface {Binterface = myInterface; luego llame a los métodos en la interfaz al igual que una definición de clase normal. ¿Por qué sería este el caso y qué beneficio podría obtener de tal declaración? –