java - interfaces - ¿Qué significa para una función devolver una interfaz?
public interface java (11)
Cuando no necesita conocer la implementación, puede devolver la interfaz para dejar la implementación a ese método y la persona que llama solo puede usar los métodos que proporciona la interfaz.
Cat cat = nextCat(state);
cat.makeCat(state);
Acabo de ver una función miembro como esta:
public Cat nextCat(GameState state);
Pero Cat es una interfaz como esta:
public interface Cat {
void makeCat(GameState state);
}
Así que estoy confundido en cuanto a cómo interpretar esto. Sé lo que significa cuando algo devuelve un objeto o un primitivo. Pero, ¿qué significa devolver una interfaz? ¿Cómo utilizar el valor de retorno de esta función?
Esta es una forma de abstracción, "Hiding Actual implementation"
, el mejor ejemplo es la interfaz del Map
, donde si alguna API tiene un tipo de retorno como Map
, el usuario no necesita preocuparse por el tipo de implementación del objeto, es decir, ''Hasmap for Hashtable'' , Con la ayuda de los métodos definidos en la interfaz del Map
, el usuario puede realizar una operación en el objeto devuelto porque la interfaz crea un contrato con las clases de implementación que la "clase de implementación debe proporcionar la definición para el método declarado" de lo contrario declara que la clase de implementación es abstract
.
Esta función devuelve un objeto de una clase que implementa la interfaz Cat. Los detalles de la implementación (para esta clase concreta) dependen de usted, siempre y cuando implemente todos los métodos de la interfaz Cat para ello.
La interfaz de retorno permite que una función miembro devuelva la referencia de cualquier clase implementada. Ofrece flexibilidad para programar una interfaz y también es útil en la implementación de patrones de diseño de fábrica y de fábrica abstracta.
Los métodos no devuelven interfaces o clases . Devuelven una referencia a una instancia (= objeto) o null
(o un valor primitivo, pero mantengámonos en los objetos). Esta referencia generalmente se almacena en una variable o se usa para llamar a los métodos de instancia o para acceder a los miembros de la instancia.
El tipo de retorno declarado nos dice el tipo menos específico de la instancia real, cuya referencia es devuelta por el método. El objeto detrás de esa referencia puede ser exactamente ese tipo o cualquier subclase (o subclase, ...).
Piensa de esta manera: si Cat
una clase regular, ¿ qué te importaría exactamente cuando quisieras llamarle algunos métodos?
Le importarán las definiciones de los métodos: sus nombres, sus tipos de argumentos, sus valores de retorno. ¡ No necesitas preocuparte por la implementación real!
Ya que una interfaz proporciona todo eso, puedes invocar métodos en ella, al igual que puedes hacerlo en una clase regular.
Por supuesto, para que el método realmente devuelva algún objeto, debe haber alguna clase que implemente esa interfaz en algún lugar . Pero la clase que realmente es o la forma en que implementa esos métodos realmente no importa al código que devuelve ese objeto.
En otras palabras, puedes escribir código como este:
Cat cat = nextCat(GameState.STUFF);
cat.makeCat(GameState.OTHER_STUFF);
Ese código no tiene conocimiento del tipo concreto que implementa la interfaz Cat
, pero sabe que el objeto puede hacer todo lo que requiere la interfaz Cat
.
Por ejemplo, podrías hacer esto:
interface Cat {
String meeeeow();
}
public Cat nextCat(GameState state) {
return new Cat() {
public String meeeeow() {
return "meeeeeeeeeow!!!!";
}
};
}
en cuyo caso el método nextCat devuelve una implementación de la interfaz Cat por medio de una ''clase anónima-interna''. Esto muestra que el código que llama a nextCat no necesita saber qué código implementa la interfaz Cat devuelta. Este es un ejemplo de una de las fortalezas clave de la programación orientada a objetos: como el código que llama no conoce la implementación, el impacto de cambiar la implementación más adelante es pequeño (siempre que la interfaz siga siendo la misma).
Según la definición orientada a objetos, una interfaz es un grupo de métodos relacionados con cuerpos vacíos. Las interfaces forman un contrato entre la clase y el mundo exterior, y este contrato se aplica en el momento de la compilación por parte del compilador. Dicho esto, nextCat(GameState state)
devuelve una Interface Cat, lo que significa que en tiempo de ejecución podría devolver cualquier objeto que implemente Cat. Ahora, ¿no es eso flexible? Los clientes no son conscientes de los tipos específicos de objetos que utilizan, siempre que los objetos se adhieran a la interfaz que los clientes esperan.
Significa, que la función miembro puede devolver cualquier implementación. Esto sigue el "Programa para una interfaz, no una implementación". patrón de diseño .
Un método no puede devolver nada (nulo), ni un valor primitivo int, double, ...), o una referencia que sea nula o se refiera a una instancia. Cuando un método devuelve una referencia, se declara que devuelve una referencia a algún tipo particular de objeto.
En su caso, la referencia que devuelve este método será nula o se referirá a un objeto cuya clase implementa Cat
Vale la pena enfatizar una vez más que es perfectamente legal, y de hecho muy común, tener variables cuyo tipo sea una interfaz, como:
Measurable meas; //"Measurable" is an interface name.
Solo recuerda que el objeto al que se refiere meas no tiene un tipo Medible.
De hecho, ningún objeto tiene tipo medible. En su lugar, el tipo de objeto es alguna clase que implementa la interfaz Medible. Esto podría ser un objeto de la clase BankAccount o la clase Coin, o alguna otra clase.
meas = new BankAccount(1000); // OK
meas = new Coin(0.1, "dime"); // OK
¿Qué puede hacer con una variable de interfaz, dado que no conoce la clase del objeto al que hace referencia?
Puedes invocar los métodos de la interfaz:
double m = meas.getMeasure();
y también debe saber que puede haber conversores de tipo entre los tipos de clase e interfaz.