JAVA4
Y
finalmente, el último nivel de acceso es el que se obtiene si no se especifica
ningún otro nivel de acceso a los miembros. Este nivel de acceso permite que
las clases del mismo paquete que la clase tengan acceso a los miembros. Este
nivel de acceso asume que las clases del mismo paquete son amigas de confianza.
Este nivel de confianza es como la que extiende a sus mejores amigos y que
incluso no la tiene con su familia.
Por
ejemplo, esta versión de la clase Alpha declara una variable y un método con
acceso de paquete. Alpha reside en el paquete Griego.
package
Griego;
class
Alpha {
int
estoyEmpaquetado;
void
metodoEmpaquetado() {
System.out.println("metodoEmpaquetado");
}
}
La
clase Alpha tiene acceso a estoyEmpaquetado y a
metodoEmpaquetado().
Además,
todas las clases declaradas dentro del mismo paquete como Alpha también tienen
acceso a estoyEmpaquetado y metodoEmpaquetado().
Supongamos
que tanto Alpha como Beta son declaradas como parte del paquete Griego.
package
Griego;
class
Beta {
void
metodoAccesor() {
Alpha
a = new Alpha();
a.estoyEmpaquetado
= 10; // legal
a.metodoEmpaquetado();
// legal
}
}
Entonces
Beta puede acceder legalmente a estoyEmpaquetado y metodoEmpaquetado().
Todas
las clases Java tienen métodos especiales llamados Constructores que se
utilizan para inicializar un objeto nuevo de ese tipo. Los contructores tienen
el mismo nombre que la clase –el nombre del constructor de la clase Rectangle
es Rectangle(), el nombre del constructor de la clase Thread es Thread(),
etc...
Java
soporta la sobrecarga de los nombres de métodos, por lo que una clase puede
tener cualquier número de constructores, todos los cuales tienen el mismo
nombre. Al igual que otros métodos sobrecargados, los constructores se
diferencian unos de otros en el número y tipo de sus argumentos.
Consideremos
la clase Rectangle del paquete java.awt que proporciona varios constructores
diferentes, todos llamados Rectangle(), pero cada uno con número o tipo
diferentes de argumentos a partir de los cuales se puede crear un nuevo objeto
Rectangle. Aquí tiene las firmas de los constructores de la clase
java.awt.Rectangle.
public
Rectangle()
public
Rectangle(int width, int height)
public
Rectangle(int x, int y, int width, int height)
public
Rectangle(Dimension size)
public
Rectangle(Point location)
public
Rectangle(Point location, Dimension size)
El
primer constructor de Rectangle inicializa un nuevo Rectangle con algunos
valores por defecto razonables, el segundo constructor inicializa el nuevo
Rectangle con la altura y anchura especificadas, el tercer constructor
inicializa el nuevo Rectangle en la posición especificada y con la altura y
anchura especificadas, etc...
Típicamente,
un constructor utiliza sus argumentos para inicializar el estado del nuevo
objeto. Entonces, cuando se crea un objeto, se debe elegir el constructor cuyos
argumentos reflejen mejor cómo se quiere inicializar el objeto.
Basándose
en el número y tipos de los argumentos que se pasan al constructor, el
compilador determina cual de ellos utilizar, Así el compilador sabe que cuando
se escribe.
new
Rectangle(0, 0, 100, 200);
el
compilador utilizará el constructor que requiere cuatro argumentos enteros, y
cuando se escribe.
new
Rectangle(miObjetoPoint, miObjetoDimension);
utilizará
el constructor que requiere como argumentos un objeto Point y un objeto
Dimension.
Cuando
escriba sus propias clases, no tendra porque proporcionar constructores. El
constructor por defecto, el constructor que no necesita argumentos, lo
proporciona automáticamente el sistema para todas las clases. Sin embargo,
frecuentemente se querrá o necesitará proporcionar
constructores
para las clases.
Se
puede declarar e implementar un constructor como se haría con cualquier otro método
en una clase. El nombre del constructor debe ser el mismo que el nombre de la
clase y, si se proporciona más de un constructor, los argumentos de cada uno de
los constructores deben diferenciarse en el número o tipo. No se tiene que
especificar el valor de retorno del constructor.
El
constructor para esta subclase de Thread, un hilo que realiza animación,
selecciona algunos valores por defecto como la velocidad de cuadro, el número
de imágenes y carga las propias imágenes.
class
AnimationThread extends Thread {
int
framesPerSecond;
int
numImages;
Image[]
images;
AnimationThread(int
fps, int num) {
int
i;
super("AnimationThread");
this.framesPerSecond
= fps;
this.numImages
= num;
this.images
= new Image[numImages];
for
(i = 0; i <= numImages; i++) {
.
. .
//
Carga las imágenes
.
. .
}
}
}
Observa
cómo el cuerpo de un constructor es igual que el cuerpo de cualquier otro método
-- contiene declaraciones de variables locales, bucles, y otras sentencias. Sin
embargo, hay una línea en el constructor de AnimationThread que no se verá en
un método normal--la segunda línea.
super("AnimationThread");
Esta
línea invoca al constructor proporcionado por la superclase de
AnimationThread--Thread. Este constructor particular de Thread acepta una cadena
que contiene el nombre del Thread.
Frecuentemente
un constructor se aprovechará del código de inicialización escrito para la
superclase de la clase.
En
realidad, algunas clases deben llamar al constructor de su superclase para que
el objeto trabaje de forma apropiada. Típicamente, llamar al constructor de la
superclase es lo primero que se hace en el constructor de la subclase: un objeto
debe realizar primero la inicialización de nivel superior.
Cuando
se declaren constructores para las clases, se pueden utilizar los
especificadores de acceso normales para especificar si otros objetos pueden
crear ejemplares de su clase.
private
Niguna
otra clase puede crear un objeto de su clase.
La
clase puede contener métodos públicos y esos métodos pueden construir un
objeto y devolverlo, pero nada más.
protected
Sólo
las subclases de la clase pueden crear ejemplares de ella.
public
Cualquiera
puede crear un ejemplar de la clase.
package-access
Nadie
externo al paquete puede construir un ejemplar de su clase.
Esto
es muy útil si se quiere que las clases que tenemos en un paquete puedan crear
ejemplares de la clase pero no se quiere que lo haga nadie más.
Escribir
un Método finalize()
Antes
de que un objeto sea recolectado por el recolector de basura, el sistema llama
al método finalize(). La intención de este método es liberar los
recursos del sistema, como ficheros o conexiones abiertas antes de empezar la
recolección.
Una
clase puede proporcionar esta finalización simplemente definiendo e
implementando un método llamado finalize(). El método finalize() debe
declararse de la siguiente forma.
protected
void finalize () throws throwable
Esta
clase abre un fichero cuando se construye.
class
AbrirUnFichero {
FileInputStream
unFichero = null;
AbrirUnFichero
(String nombreFichero) {
try
{
unFichero
= new FileInputStream(nombreFichero);
}
catch (java.io.FileNotFoundException e) {
System.err.println("No
se pudo abrir el fichero " + nombreFichero);
}
}
}
Para
un buen comportamiento, la clase AbrirUnFichero debería cerrar el fichero
cuando haya finalizado.
Aquí
tienes el método finalize() para la clase AbrirUnFichero.
protected
void finalize () throws throwable {
if
(unFichero != null) {
unFichero.close();
unFichero
= null;
}
}
El
método finalize() está declarado en la clase java.lang.Object. Así
cuando escribas un método finalize() para tus clases estás
sobreescribiendo el de su superclase.
Si
la superclase tiene un método finalize(), probablemente este método
deberá llamar al método finalize() de su superclase después de haber
terminado sus tareas de limpieza. Esto limpiará cualquier recurso obtenido sin
saberlo a través de los métodos heredados desde la superclase.
protected
void finalize() throws Throwable {
.
. .
//
aquí va el código de limpieza de esta clase
.
. .
super.finalize();
}
En
Java, como en otros lenguajes de programación orientados a objetos, las clases
pueden derivar desde otras clases. La clase derivada (la clase que proviene de
otra clase) se llama subclase. La clase de la que está derivada se denomina
superclase.
De
hecho, en Java, todas las clases deben derivar de alguna clase. Lo que nos lleva
a la cuestión ¿Dónde empieza todo esto?. La clase más alta, la clase de la
que todas las demás descienden, es la clase Object, definida en java.lang.
Object es la raíz de la herencia de todas las clases.
Las
subclases heredan el estado y el comportamiento en forma de las variables y los
métodos de su superclase. La subclase puede utilizar los ítems heredados de su
superclase tal y como son, o puede modificarlos o sobreescribirlos. Por eso, según
se va bajando por el árbol de la herencia, las clases se convierten en más y más
especializadas.
Definición:
Una
subclase es una clase que desciende de otra clase. Una subclase hereda el estado
y el comportamiento de todos sus ancestros. El término superclase se refiere a
la clase que es el ancestro más directo, así como a todas las clases
ascendentes.
Se
declara que un clase es una subclase de otra clase dentro de La declaración de
Clase. Por ejemplo, supongamos que queremos crear una subclase llamada SubClase
de otra clase llamada SuperClase. Se escribiría esto.
class
SubClass extends SuperClass {
.
. .
}
Esto
declara que SubClase es una subclase de SuperClase. Y también declara implícitamene
que SuperClase es la superclase de SubClase. Una subclase también hereda
variables y miembros de las superclases de su superclase, y así a lo largo del
árbol de la herencia. Para hacer esta explicación un poco más sencilla,
cuando este tutorial se refiere a la superclase de una clase significa el
ancestro más directo de la clase así como a todas sus clases ascendentes.
Una
clase Java sólo puede tener una superclase directa. Java no soporta la herencia
múltiple.
Crear
una subclase puede ser tan sencillo como incluir la clausula extends en
la declaración de la clase. Sin embargo, normalmente se deberá realizar alguna
cosa más cuando se crea una subclase, como sobreescribir métodos, etc...
¿Qué
variables miembro hereda una subclase?
Regla:
Una
subclase hereda todas las variables miembros de su superclase que puedan ser
accesibles desde la subclase (a menos que la variable miembro esté oculta en la
subclase).
Esto
es, las subclases. heredan
aquellas variables miembros declaradas como public o protected heredan
aquellas variables miembros declaradas sin especificador de acceso (normalmente
conocidas como "Amigas") siempre que la subclase esté en el mismo
paquete que la clase no hereda las variables miembros de la superclase si la
subclase declara una variable miembro que utiliza el mismo nombre. La variable
miembro de la subclase se dice que oculta a la variable miembro de la
superclase. no hereda las variables miembro private
Como
se mencionó en la sección anterior, las variables miembros definidas en la
subclase ocultan las variables miembro que tienen el mismo nombre en la
superclase.
Como
esta característica del lenguaje Java es poderosa y conveniente, puede ser una
fuente de errores: ocultar una variable miembro puede hacerse deliberadamente o
por accidente. Entonces, cuando nombres tus variables miembro se cuidadoso y
oculta sólo las variables miembro que realmente deseas ocultar.
Una
caracteristica interesante de las variables miembro en Java es que una clase
puede acceder a una variable miembro oculta a través de su superclase.
Considere este pareja de superclase y subclase.
class
Super {
Number
unNumero;
}
class
Sub extends Super {
Float
unNumero;
}
La
variable unNumero de Sub oculta a la variable unNumero de Super.
Pero se puede acceder a la variable de la superclase utilizando.
super.unNumero
super
es
una palabra clave del lenguaje Java que permite a un método referirse a las
variables ocultas y métodos sobreescritos de una superclase.
¿Qué
métodos hereda una Subclase?
La
regla que especifica los métodos heredados por una subclase es similar a la de
las variables miembro.
Regla:
Una
subclase hereda todos los métodos de sus superclase que son accesibles para la
subclase (a menos que el método sea sobreescrito por la subclase). Esto es, una
Subclase. hereda
aquellos métodos declarados como public o protected hereda
aquellos métodos sin especificador de acceso, siempre que la subclase esté en
el mismo paquete que la clase. no hereda un método de la superclase si la
subclase declara un método que utiliza el mismo nombre.
Se
dice que el método de la subclase sobreescribe al método de la superclase.
La
habilidad de una subclase para sobreescribir un método de su superclase permite
a una clase heredar de su superclase aquellos comportamientos "más
cercanos" y luego suplementar o modificar el comportamiento de la
superclase.
Una
subclase puede sobreescribir completamente la implementación de un método
heredado o puede mejorar el método añadiendole funcionalidad.
Reemplazar
la Implementación de un Método de una Superclase
Algunas
veces, una subclase querría reemplazar completamente la implementación de un método
de su superclase. De hecho, muchas superclases proporcionan implementaciones de
métodos vacías con la esperanza de que la mayoría, si no todas, sus subclases
reemplacen completamente la implementación de ese método.
Un
ejemplo de esto es el método run() de la clase Thread. La clase Thread
proporciona una implementación vacía (el método no hace nada) para el método
run(), porque por definición, este método depende de la subclase. La
clase Thread posiblemente no puede proporcionar una implementación medianamente
razonable del método run().
Para
reemplazar completamente la implementación de un método de la superclase,
simplememte se llama a un método con el mismo nombre que el del método de la
superclase y se sobreescribe el método con la misma firma que la del método
sobreescrito.
class
ThreadSegundoPlano extends Thread {
void
run() {
.
. .
}
}
La
clase ThreadSegundoPlano sobreescribe completamente el método run() de
su superclase y reemplaza completamente su implementación.
Otras
veces una subclase querrá mantener la implementación del método de su
superclase y posteriormente ampliar algún comportamiento específico de la
subclase. Por ejemplo, los métodos constructores de una subclase lo hacen
normalmente--la subclase quiere preservar la inicialización realizada por la
superclase, pero proporciona inicialización adicional específica de la
subclase.
Supongamos
que queremos crear una subclase de la clase Windows del paquete java.awt. La
clase Windows tiene un constructor que requiere un argumento del tipo Frame que
es el padre de la ventana.
public
Window(Frame parent)
Este
constructor realiza alguna inicialización en la ventana para que trabaje dentro
del sistema de ventanas.
Para
asegurarnos de que una subclase de Windows también trabaja dentro del sistema
de ventanas, deberemos proporcionar un constructor que realice la misma
inicialización.
Mucho
mejor que intentar recrear el proceso de inicialización que ocurre dentro del
constructor de Windows, podríamos utilizar lo que la clase Windows ya hace. Se
puede utilizar el código del constructor de Windows
llamámdolo
desde dentro del constructor de la subclase Window.
class
Ventana extends Window {
public
Ventana(Frame parent) {
super(parent);
.
. .
//
Ventana especifica su inicialización aquí
.
. .
}
}
El
constructor de Ventana llama primero al constructor de su superclase, y
no hace nada más.
Típicamente,
este es el comportamiento deseado de los constructores--las superclases deben
tener la oportunidad de realizar sus tareas de inicialización antes que las de
su subclase. Otros tipos de métodos podrían llamar al constructor de la
supeclase al final del método o en el medio.
Una
subclase no puede sobreescribir métodos que hayan sido declarados como final
en la superclase (por definición, los métodos finales no pueden ser
sobreescritos). Si intentamos sobreescribir un método final, el compilador
mostrará un mensaje y no compilará
el programa.
Una
subclase tampoco puede sobreescribir métodos que se hayan declarado como static
en la superclase. En otras palabras, una subclase no puede sobreescribir un
método de clase.
Las
subclases deben sobreescribir aquellos métodos que hayan sido declarados como abstract
en la superclase, o la propia subclase debe ser abstracta.
Se
puede declarar que una clase sea final; esto es, que la clase no pueda tener
subclases. Existen (al menos) dos razones por las que se querría hacer esto:
razones de seguridad y de diseño.
Seguridad:
Un mecanismo que los hackers utilizan para atacar sistemas es crear subclases de
una clase y luego sustituirla por el original. Las subclases parecen y sienten
como la clase original pero hacen cosas bastante diferentes, probablemente
causando daños u obteniendo información privada.
Para
prevenir esta clase de subversión, se puede declarar que la clase sea final y
así prevenir que se cree cualquier subclase.
La
clase String del paquete java.lang es una clase final sólo por esta razón. La
clase String es tan vital para la operación del compilador y del intérprete
que el sistema Java debe garantizar que siempre que un método o un objeto
utilicen un String, obtenga un objeto java.lang.String y no algún otro string.
Esto asegura que ningún string tendrá propiedades extrañas, incosistentes o
indeseables.
Si
se intenta compilar una subclase de una clase final, el compilador mostrará un
mensaje de error y no compilará el programa. Además, los bytescodes verifican
que no está teniendo lugar una subversión, al nivel de byte comprobando que
una clase no es una subclase de una clase final.
Diseño:
Otra razón por la que se podría querer declarar una clase final son razones de
diseño orientado a objetos. Se podría pensar que una clase es
"perfecta" o que, conceptualmente hablando, la clase no debería tener
subclases.
Para
especificar que una clase es una clase final, se utiliza la palabra clave final
antes de la palabra clave class en la declaración de la clase. Por
ejemplo, si quisieramos declarar AlgoritmodeAjedrez como una clase final
(perfecta), la declaración se parecería a esto.
final
class AlgoritmodeAjedrez {
.
. .
}
Cualquier
intento posterior de crear una subclase de AlgoritmodeAjedrez resultará en un
error del compilador.
Si
la creacción de clases finales parece algo dura para nuestras necesidades, y
realmente lo que se quiere es proteger son algunos métodos de una clase para
que no sean sobreescritos, se puede utilizar la palabra clave final en la
declaración de método para indicar al compilador que este método no puede ser
sobreescrito por las subclases.
Se
podría desear hacer que un método fuera final si el método tiene una
implementación que no debe ser cambiada y que es crítica para el estado
consistente del objeto. Por ejemplo, en lugar de hacer AlgoritmodeAjedrez como
una clase final, podríamos hacer siguienteMovimiento() como un método
final.
class
AlgoritmodeAjedrez {
.
. .
final
void siguienteMovimiento(Pieza piezaMovida,
PosicionenTablero
nuevaPosicion) {
}
.
. .
}
Algunas
veces, una clase que se ha definido representa un concepto abstracto y como tal,
no debe ser ejemplarizado. Por ejemplo, la comida en la vida real. ¿Has visto
algún ejemplar de comida? No.
Lo
que has visto son ejemplares de manzanas, pan, y chocolate. Comida representa un
concepto abstracto de cosas que son comestibles. No tiene sentido que exista un
ejemplar de comida.
Similarmente
en la programación orientada a objetos, se podrían modelar conceptos
abstractos pero no querer que se creen ejemplares de ellos. Por ejemplo, la
clase Number del paquete java.lang representa el concepto abstracto de número.
Tiene sentido modelar números en un programa, pero no tiene sentido crear un
objeto genérico de números. En su lugar, la clase Number sólo tiene sentido
como superclase de otras clases como Integer y Float que implementan números de
tipos específicos. Las clases como Number, que implementan conceptos abstractos
y no deben ser ejemplarizadas, son llamadas clases abstractas. Una clase
abstracta es una clase que sólo puede tener subclases--no puede ser
ejemplarizada.
Para
declarar que una clase es un clase abstracta, se utiliza la palabra clave abstract
en la declaración de la clase.
abstract
class Number {
.
. .
}
Si
se intenta ejemplarizar una clase abstracta, el compilador mostrará un error y
no compilará el programa.
Una
clase abstracta puede contener métodos abstractos, esto es, métodos que no
tienen implementación. De esta forma, una clase abstracta puede definir un
interface de programación completo, incluso porporciona a sus subclases la
declaración de todos los métodos necesarios para implementar el interface de
programación. Sin embargo, las clases abstractas pueden dejar algunos detalles
o toda la implementación de aquellos métodos a sus subclases.
Veamos
un ejemplo de cuando sería necesario crear una clase abstracta con métodos
abstractos. En una aplicación de dibujo orientada a objetos, se pueden dibujar
círculos, rectángulos, líneas, etc.. Cada uno de esos objetos gráficos
comparten ciertos estados (posición, caja de dibujo) y comportamiento
(movimiento, redimensionado, dibujo). Podemos
provecharnos de esas similitudes y declararlos todos a partir de un mismo
objeto padre-ObjetoGrafico.
Sin
embargo, los objetos gráficos también tienen diferencias subtanciales: dibujar
un círculo es bastante diferente a dibujar un rectángulo. Los objetos gráficos
no pueden compartir estos tipos de estados o comportamientos. Por otro lado,
todos los ObjetosGraficos deben saber como dibujarse a sí mismos; se
diferencian en cómo se dibujan unos y otros. Esta es la situación perfecta
para una clase abstracta.
Primero
se debe declarar una clase abstracta, ObjetoGrafico, para proporcionar las
variables miembro y los métodos que van a ser compartidos por todas las
subclases, como la posición actual y el método moverA().
También
se deberían declarar métodos abstractos como dibujar(), que necesita
ser implementado por todas las subclases, pero de manera completamente diferente
(no tiene sentido crear una implementación por defecto en la superclase). La
clase ObjetoGrafico se parecería a esto.
abstract
class ObjetoGrafico {
int
x, y;
.
. .
void
moverA(int nuevaX, int nuevaY) {
.
. .
}
abstract
void dibujar();
}
Todas
las subclases no abstractas de ObjetoGrafico como son Circulo o Rectangulo deberán
proprocionar una implementación para el método dibujar().
class
Circulo extends ObjetoGrafico {
void
dibujar() {
.
. .
}
}
class
Rectangulo extends ObjetoGrafico {
void
dibujar() {
.
. .
}
}
Una
clase abstracta no necesita contener un método abstracto. Pero todas las clases
que contengan un método abstracto o no proporcionen implementación para
cualquier método abstracto declarado en sus superclases debe ser declarada como
una clase abstracta.
La
clase Object está situada en la parte más alta del árbol de la herencia en el
entorno de desarrollo de Java. Todas las clases del sistema Java son
descendentes (directos o indirectos) de la clase Object. Esta clase define los
estados y comportamientos básicos que todos los objetos deben tener, como la
posibilidad de compararse unos con otros, de convertirse a cadenas, de esperar
una condición variable, de notificar a otros objetos que la condición varible
a cambiado y devolver la clase del objeto.
El
método equals()
equals()
se
utiliza para comparar si dos objetos son iguales. Este método devuelve true si
los objetos son iguales, o false si no lo son. Observe que la igualdad no
significa que los objetos sean el mismo objeto. Consideremos este código que
compara dos enteros.
Integer
uno = new Integer(1), otroUno = new Integer(1);
if
(uno.equals(otroUno))
System.out.println("Los
objetos son Iguales");
Este
código mostrará Los objetos son Iguales aunque uno y otroUno referencian
a dos objetos distintos. Se les considera iguales porque su contenido es el
mismo valor entero.
Las
clases deberían sobreescribir este método proporcionando la comprobación de
igualdad apropiada. Un método equals() debería comparar el contenido de
los objetos para ver si son funcionalmente iguales y devolver true si es
así.
El
método getClass()
El
método getClass() es un método final (no puede sobreescribirse) que
devuelve una representación en tiempo de ejecución de la clase del objeto.
Este método devuelve un objeto Class al que se le puede pedir varia información
sobre la clase, como su nombre, el nombre de su superclase y los nombres de los
interfaces que implementa. El siguiente método obtiene y muestra el nombre de
la clase de un objeto.
void
PrintClassName(Object obj) {
System.out.println("La
clase del Objeto es " +
obj.getClass().getName());
}
Un
uso muy manejado del método getClass() es crear un ejemplar de una clase
sin conocer la clase en el momento de la compilación. Este método de ejemplo,
crea un nuevo ejemplar de la misma clase que obj que puede ser cualquier
clase heredada desde Object (lo que significa que podría ser cualquier clase).
Object
createNewInstanceOf(Object obj) {
return
obj.getClass().newInstance();
}
El
método toString()
Este
método devuelve una cadena de texto que representa al objeto. Se puede utilizar
toString para mostrar un objeto. Por ejemplo, se podría mostrar una
representación del Thread actual de la siguiente forma.
System.out.println(Thread.currentThread().toString());
System.out.println(new
Integer(44).toString());
La
representación de un objeto depende enteramente del objeto. El String de un
objeto entero es el valor del entero mostrado como texto. El String de un objeto
Thread contiene varios atributos sobre el thread, como su nombre y prioridad.
Por ejemplo, las dos líneas anteriores darían la siguiente salida.
Thread[main,5,main]
El
método toString() es muy útil para depuración y también puede s
obreescribir este método en todas las clases.
Otros
métodos de Object cubiertos en otras lecciones o secciones
La
clase Object proporciona un método, finalize() que limpia un objeto
antes de recolectar la basura.
La
clase Object tambiém proporciona otros cinco métodos.
notify()
notifyAll()
wait()
(tres
versiones)
que
son críticos cuando se escriben programas Java con múltiples thread. Estos métodos
ayudan a asegurarse que los thread están sincronizados y se cubren en Threads
de Control.
¿Qué
es un Interface?
Definición:
Un
interface es una colección de definiciones de métodos (sin implementaciones) y
de valores constantes.
Los
interfaces se utilizan para definir un protocolo de comportamiento que puede ser
implementado por cualquier clase del árbol de clases.
Los
interfaces son útiles para.
capturar
similitudes entre clases no relacionadas sin forzar una relación entre ellas.
declarar métodos que una o varias clases necesitan implementar.
revelar
el interface de programación de un objeto sin recelar sus clases (los objetos
de este tipo son llamados objetos anónimos y pueden ser útiles cuando
compartas un paquete de clases con otros desarrolladores).
En
Java, un interface es un tipo de dato de referencia, y por tanto, puede
utilizarse en muchos de los sitios donde se pueda utilizar cualquier tipo (como
en un argumento de métodos y una declaración de variables).
Los
Interfaces No Proporcionan Herencia Múltiple
Algunas
veces se tratra a los interfaces como una alternativa a la herencia múltiple en
las clases. A pesar de que los interfaces podrían resolver algunos problemas de
la herencia múltiple, son animales bastantes diferentes.
No
se pueden heredar variables desde un interface.
No
se pueden heredar implementaciones de métodos desde un interface.
La
herencia de un interface es independiente de la herencia de la clase--las clases
que implementan el mismo interface pueden o no estar relacionadas a través del
árbol de clases.