|
Clases |
Anterior | Siguiente |
Las clases son lo más simple de Java. Todo en Java forma parte de una clase, es una clase o describe como funciona una clase. El conocimiento de las clases es fundamental para poder entender los programas Java.Todas las acciones de los programas Java se colocan dentro del bloque de una clase o un objeto. Un objeto es una instancia de una clase. Todos los métodos se definen dentro del bloque de la clase, Java no soporta funciones o variables globales. Esto puede despistar a los programadores de C++, que pueden definir métodos fuera del bloque de la clase, pero esta posibilidad es más un intento de no separarse mucho y ser compatible con C, que un buen diseño orientado a objetos. Así pues, el esqueleto de cualquier aplicación Java se basa en la definición de una clase. Todos los datos básicos, como los enteros, se deben declarar en las clases antes de hacer uso de ellos. En C la unidad fundamental son los ficheros con código fuente, en Java son las clases. De hecho son pocas las sentencias que se pueden colocar fuera del bloque de una clase. La palabra clave import (equivalente al #include) puede colocarse al principio de un fichero, fuera del bloque de la clase. Sin embargo, el compilador reemplazará esa sentencia con el contenido del fichero que se indique, que consistirá, como es de suponer, en más clases. La definición de una clase consta de dos partes, la declaración y el cuerpo, según la siguiente sintaxis: DeclaracionClase { CuerpoClase } sin el punto y coma (;) final característico de C++ para señalar el final de la definición de una clase. La declaración de la clase indica al compilador el nombre de la clase, la clase de la que deriva (su superclase), los privilegios de acceso a la clase (pública, abstracta, final) y si la clase implementa o no, uno o varios interfaces. El nombre de la clase debe ser un identificador válido en Java. Por convención, muchos programadores Java empiezan el nombre de las clase Java con una letra mayúscula. Cada clase Java deriva, directa o indirectamente, de la clase Object. La clase padre inmediatamente superior a la clase que se está declarando se conoce como superclass. Si no se especifica la superclase de la que deriva una clase, se entiende que deriva directamente de la clase Object (definida en el paquete java.lang). En la declaración de una clase se utiliza la palabra clave extends para especificar la superclase, de la forma: class MiClase extends SuperClase { // cuerpo de la clase } Los programadores C++ observarán que no se indica nada sobre los privilegios de acceso a la clase, es decir, si es pública, privada o protegida. O sea, la herencia de los métodos de acceso a una clase no se pueden utilizar en Java para modificar el control de acceso asignado a un miembro de la clase padre. Al igual que en C++, una clase hereda las variables y métodos de su superclase y de la superclase de esa clase, etc.; es decir, de todo el árbol de jerarquía de clases desde la clase que estamos declarando hasta la raíz del árbol: Object. En otras palabras, un objeto que es instanciado desde una clase determinada, contiene todas las variables y métodos de instancia definidos para esta clase y sus antecesores; aunque los métodos pueden ser modificados (sobreescritos) en algún lugar. Una clase puede implementar uno o más interfaces, declarándose esto utilizando la palabra clave implements, seguida de la lista de interfaces que implementa, se paradas por coma (,), de la forma: class MiClase extends SuperClase implements MiInterfaz,TuInterfaz { // cuerpo de la clase } Cuando una clase indique que implementa un interfaz, se puede asegurar que proporciona una definición para todos y cada uno de los métodos declarados en ese interfaz; en caso contrario, el compilador generará errores al no poder resolver los métodos del interfaz en la clase que lo implementa. Hay cierta similitud entre un interfaz y una clase abstracta, aunque las definiciones de métodos no están permitidas en un interfaz y sí se pueden definir en una clase abstracta. El propósito de los interfaces es proporcionar nombres, es decir, solamente declara lo que necesita implementar el interfaz, pero no cómo se ha de realizar esa implementación; es una forma de encapsulación de los protocolos de los métodos sin forzar al usuario a utilizar la herencia. Cuando se implementa un interfaz, los nombres de los métodos de la clase deben coincidir con los nombres de los métodos que están declarados en es interfaz, todos y cada uno de ellos. El cuerpo de la clase contiene las declaraciones, y posiblemente la inicialización, de todos los datos miembros, tanto variables de clase como variables de instancia, y la definición completa de todos los métodos. Las variables pueden declararse dentro del cuerpo de la clase o dentro del cuerpo de un método de la clase. Sin embargo, éstas últimas no son variables miembro de la clase, sino variables locales del método en la que están declaradas. Un objeto instanciado de una clase tiene un estado definido por el valor actual de las variables de instancia y un entorno definido por los métodos de instancia. Es típico de la programación orientada a objetos el restringir el acceso a las variables y proporcionar métodos que permitan el acceso a esas variables, aunque esto no es estrictamente necesario. Alguna o todas las variables pueden declararse para que se comporten como si fuesen constantes, utilizando la palabra clave final. Los objetos instanciados desde una clase contienen todos los métodos de instancia de esa clase y también todos los métodos heredados de la superclase y sus antecesores. Por ejemplo, todos los objetos en Java heredan, directa o indirectamente, de la clase Object; luego todo objeto contiene los miembros de la clase Object, es decir, la clase Object define el esta y entorno básicos para todo objeto Java. Esto difiere significativamente de C++, en donde no hay una clase central de la que se derive todo, por lo que no hay una definición de un estado básico en C++. Las características más importantes que la clase Object cede a sus descendientes son:
Hay muchas otras características que se irán viendo a lo largo de los ejemplos y secciones del Tutorial. La sintaxis general de definición de clase se podría extender tal como se muestra en el siguiente diagrama, que debe tomarse solamente como referencia y no al pie de la letra: NombreDeLaClase { // declaración de las variables de instancia // declaración de las variables de la clase metodoDeInstancia() { // variables locales // código } metodoDeLaClase() { // variables locales // código } } Hasta ahora sólo se ha utilizado la palabra clave public para calificar el nombre de las clases que hemos visto, pero hay tres modificadores más. Los tipos de clases que podemos definir son: Las clases public son accesibles desde otras clases, bien sea directamente o por herencia, desde clases declaradas fuera del paquete que contiene a esas clases públicas, ya que, por defecto, las clases solamente son accesibles por otras clases declaradas dentro del mismo paquete en el que se han declarado. Para acceder desde otros paquetes, primero tienen que ser importadas. La sintaxis es: public class miClase extends SuperClase implements miInterface,TuInterface { // cuerpo de la clase } Aquí la palabra clave public se utiliza en un contexto diferente del que se emplea cuando se define internamente la clase, junto con private y protected. Una clase abstract tiene al menos un método abstracto. Una clase abstracta no se instancia, sino que se utiliza como clase base para la herencia. Es el equivalente al prototipo de una función en C++. Una clase final se declara como la clase que termina una cadena de herencia, es lo contrario a una clase abstracta. Nadie puede heredar de una clase final. Por ejemplo, la clase Math es una clase final. Aunque es técnicamente posible declarar clases con varias combinaciones de public, abstract y final, la declaración de una clase abstracta y a la vez final no tiene sentido, y el compilador no permitirá que se declare una clase con esos dos modificadores juntos. Este modificador especifica que todos los métodos definidos en la clase son sincronizados, es decir, que no se puede acceder al mismo tiempo a ellos desde distintos threads; el sistema se encarga de colocar los flags necesarios para evitarlo. Este mecanismo hace que desde threads diferentes se puedan modificar las mismas variables sin que haya problemas de que se sobreescriban. Si no se utiliza alguno de los modificadores expuestos, por defecto, Java asume que una clase es:
|
|