1. Introducción a las interfaces
Hoy es tu día para el conocimiento. Otro tema nuevo e interesante son las interfaces.
El concepto de interfaz es hijo de los principios de abstracción y polimorfismo. Una interfaz es muy similar a una clase abstracta, en la que todos los métodos son abstractos. Se declara de la misma forma que una clase, pero usamos la interface
palabra clave.
interface Feline
{
void purr();
void meow();
void growl();
}
Aquí hay algunos datos útiles sobre las interfaces:
1. Declarar una interfaz
interface Drawable
{
void draw();
}
interface HasValue
{
int getValue();
}
- En lugar de la
class
palabra clave, escribimosinterface
. - Contiene solo métodos abstractos (no escriba la
abstract
palabra clave) - De hecho, las interfaces tienen todos
public
los métodos
Una interfaz solo puede heredar interfaces. Pero una interfaz puede tener muchos padres. Otra forma de decir esto es decir que Java tiene herencia múltiple de interfaces. Ejemplos:
interface Piece extends Drawable, HasValue
{
int getX();
int getY();
}
3. Heredar clases de interfaces
Una clase puede heredar múltiples interfaces (solo de una clase). Esto se hace usando la implements
palabra clave. Ejemplo:
abstract class ChessItem implements Drawable, HasValue
{
private int x, y, value;
public int getValue()
{
return value;
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
}
La clase ChessItem se declara abstracta: implementa todos los métodos heredados excepto draw
. En otras palabras, la ChessItem
clase contiene un método abstracto: draw()
.
El significado técnico de las palabras clave extends
y implements
es el mismo: ambas son herencia. La distinción se hizo para mejorar la legibilidad del código. También decimos que las clases se heredan (vía extends
) y las interfaces se implementan (vía implements
)
4. Variables
Aquí está lo más importante: las variables ordinarias no se pueden declarar en las interfaces (aunque las estáticas sí).
Pero, ¿por qué necesitamos interfaces? ¿Cuándo se usan? Las interfaces tienen dos fuertes ventajas sobre las clases:
2. Separar la "descripción de métodos" de su implementación.
Anteriormente, dijimos que si desea permitir que los métodos de su clase sean llamados desde otras clases, entonces sus métodos deben estar marcados con la public
palabra clave. Si desea que algunos de esos métodos se llamen solo desde dentro de su clase, debe marcarlos con la private
palabra clave. En otras palabras, dividimos los métodos de la clase en dos categorías: "para que todos los usen" y "solo para nuestro propio uso".
Las interfaces ayudan a fortalecer aún más esta división. Haremos una "clase especial para que todos la usen", así como una segunda clase "solo para nuestro propio uso", que heredará la primera clase. Así es más o menos cómo se vería:
Antes | Después |
---|---|
|
|
|
|
Dividimos nuestra clase en dos: una interfaz y una clase que hereda la interfaz . ¿Y cuál es la ventaja aquí?
Muchas clases diferentes pueden implementar (heredar) la misma interfaz. Y cada uno puede tener su propio comportamiento. Por ejemplo, ArrayList
LinkedList
son dos implementaciones diferentes de la List
interfaz.
Por lo tanto, ocultamos no solo las diversas implementaciones, sino también la propia clase de implementación (ya que solo necesitamos la interfaz en el código). Esto nos permite ser muy flexibles: justo cuando el programa se ejecuta, podemos reemplazar un objeto con otro, cambiando el comportamiento de un objeto sin afectar a todas las clases que lo usan.
Esta es una técnica muy poderosa cuando se combina con polimorfismo. Por ahora, está lejos de ser obvio por qué deberías hacer esto. Primero debe encontrar programas con docenas o cientos de clases para comprender que las interfaces pueden hacer su vida mucho más fácil que sin ellas.
3. Herencia múltiple
En Java, todas las clases solo pueden tener una clase principal. En otros lenguajes de programación, las clases a menudo pueden tener varias clases principales. Esto es muy conveniente, pero también trae muchos problemas.
Los creadores de Java llegaron a un compromiso: prohibieron la herencia múltiple de clases, pero permitieron la herencia múltiple de interfaces. Una interfaz puede tener varias interfaces principales. Una clase puede tener varias interfaces principales, pero solo una clase principal.
¿Por qué prohibieron la herencia múltiple de clases pero permitieron la herencia múltiple de interfaces? Debido al llamado problema de herencia de diamantes:

Cuando la clase B hereda la clase A, no sabe nada de las clases C y D. Por lo tanto, utiliza las variables de la clase A como mejor le parezca. La clase C hace lo mismo: utiliza las variables de la clase A, pero de forma diferente. Y todo esto resulta en un conflicto en la clase D.
Veamos el siguiente ejemplo sencillo. Digamos que tenemos 3 clases:
class Data
{
protected int value;
}
class XCoordinate extends Data
{
public void setX (int x) { value = x;}
public int getX () { return value;}
}
class YCoordinate extends Data
{
public void setY (int y) { value = y;}
public int getY () { return value; }
}
La clase de datos almacena la value
variable. Su clase descendiente XCoordinate usa esa variable para almacenar el x
valor, y la YCoordinate
clase descendiente la usa para almacenar el y
valor.
Y funciona. Por separado. Pero si queremos que la clase XYCoordinates herede las clases XCoordinate
y YCoordinate
, obtenemos un código roto. Esta clase tendrá los métodos de sus clases antepasadas, pero no funcionarán correctamente porque tienen el mismo value variable
.
Pero debido a que las interfaces no pueden tener variables, no pueden tener este tipo de conflicto. En consecuencia, se permite la herencia múltiple de interfaces.
GO TO FULL VERSION