Você está na página 1de 27

Clases1

Contenido
Clases
Contenido
Introduccin
Declaracin de clases
Declaracin de variables
Modificadores de acceso
Tipos
Nombres de variables
Definicin de mtodos
Nombrar a un mtodo
Mtodos con sobrecarga
Definicin de constructores
Pasar informacin a un mtodo o constructor
Tipos de parmetros
Un nmero arbitrario de argumentos
Los nombres de parmetros
Pasando argumentos de tipos de datos primitivos
Pasando argumentos de tipo de datos de referencia
Devolver un valor desde un mtodo
Devolucin de una clase o interfaz
Uso de la palabra clave this
El uso de this con un atributo
El uso de this con un constructor
Control de acceso a miembros de una clase
Entendiendo a los miembros de instancia y de clase
Variables de clase
Mtodos de clase
Constantes
La clase Bicicleta
Inicializacin de atributos
Bloques estticos de inicializacin
Inicializacin de los miembros de instancia
Preguntas y Ejercicios
Preguntas
Ejercicios

1 Este es un intento de traduccin al espaol de The Java Tutorials, Lesson: Classes and Objects.

Introduccin
Recordemos nuestro ejemplo de la clase de Bicicleta y sus subclases
BicicletaDeCarrera, BicicletaDeMontaa y BicicletaBMX. El siguiente cdigo
muestra una posible implementacin de la clase Bicicleta para ejemplificar la declaracin de
una clase. Posteriormente estudiaremos cada detalle de la declaracin de una clase.
public class Bicicleta {
// La clase Bicicleta tiene tres atributos
public int cadencia;
public int velocidad;
public int desplazamiento;
// La clase Bicicleta tiene un constructor
public Bicicleta(int cadenciaInicial, int desplazamientoInicial,
int velocidadInicial) {
velocidad = velocidadInicial;
cadencia = cadenciaInicial;
desplazamiento = desplazamientoInicial;
}
// La clase Bicicleta tiene cuatro mtodos
public void establecerCadencia(int nuevoValor) {
cadencia = nuevoValor;
}
public void establecerVelocidad(int nuevoValor) {
velocidad = nuevoValor;
}
public void frenar(int decremento) {
desplazamiento -= decremento;
}
public void acelerar(int incremento) {
desplazamiento += incremento;
}
}

Un ejemplo de declaracin de la clase BicicletaDeMontaa, que es una subclase de


Bicicleta, podra ser la siguiente:
public class BicicletaDeMontana extends Bicicleta {

// La subclase BicicletaDeMontana tiene un atributo adicional


// a los heredados de la clase Bicicleta
public int alturaAsiento;
// La subclase BicicletaDeMontana tiene un constructor
public BicicletaDeMontana(int alturaInicial,
int cadenciaInicial,
int desplazamientoInicial,
int velocidadInicial) {
super(cadenciaInicial, desplazamientoInicial,
velocidadInicial);
alturaAsiento = alturaInicial;
}
// La subclase BicicletaDeMontana tiene un mtodo
public void establecerAltura(int nuevoValor) {
alturaAsiento = nuevoValor;
}
}
BicicletaDeMontana hereda todos los campos y mtodos de Bicicleta y agrega el
atributo alturaAsiento y un mtodo para establecerla (las bicicletas de montaa tienen
asientos que se pueden mover hacia arriba y hacia abajo de acuerdo con el tipo de terreno).

Declaracin de clases
Hemos visto que las clases se definen de la siguiente forma:
class MiClase {
// declaraciones de atributos, constructores y mtodos
}
Esta es una declaracin de clase. El cuerpo de la clase (el espacio entre las llaves) contiene
todo el cdigo que establece el ciclo de vida de los objetos creados a partir de la clase:
constructores para inicializar nuevos objetos, las declaraciones de los atributos que
proporcionan el estado de la clase y sus objetos y mtodos para implementar el
comportamiento de la clase y sus objetos.
La declaracin anterior es mnima, ya que slo contiene los componentes que se requieren en
una declaracin de clase. Podemos dar ms informacin acerca de la clase, como el nombre
de la superclase, si implementa alguna de las interfaces y as sucesivamente, en el inicio de la
declaracin de la clase. Por ejemplo,
class MiClase extends MiSuperClase implements TuInterfaz {

// declaraciones de atributos, constructores y mtodos


}
significa que MiClase es una subclase de MiSuperClase y que implementa la interfaz
TuInterfaz.
Tambin se puede agregar uno de los modificadores public o private en el inicio, de esta
forma vemos que la primera lnea de una declaracin de clase puede complicarse un poco
ms. Los modificadores public y private, que determinan lo que pueden acceder otras
clases de MiClase, se estudiar ms adelante. Cuando estudiemos interfaces y la herencia se
explicar cmo y por qu se deben utilizar las palabras reservadas extends e implements
en una declaracin de clase.
En general, cuando se declara una clase se pueden incluir los siguientes componentes, en este
orden:
Los modificadores public y private.
El nombre de la clase, por convencin con la letra inicial mayscula.
El nombre del padre (superclase) de la clase, en su caso, precedido por la
palabra reservada extends. Una clase slo puede heredar (subclase) a un padre.
Una lista separada por comas de interfaces implementadas por la clase, en su
caso, precedida por la palabra reservada implements. Una clase puede implementar
ms de una interfaz.
El cuerpo de la clase, encerrada entre llaves {}.

Declaracin de variables
Hay diferentes tipos de variables:
Las variables de la clase, que son los atributos.
Las variables dentro de un mtodo o bloque, llamadas variables locales.
Las variables en la declaracin de un mtodo, que se conocen como
parmetros.
La clase de Bicicleta utiliza las siguientes lneas de cdigo para definir sus atributos:
public int cadencia;
public int velocidad;
public int desplazamiento;
Las declaraciones de atributos estn conformadas de tres componentes, en este orden:
1. Cero o ms modificadores, como public o private.
2. El tipo del atributo.
3. El nombre del atributo.

Los atributos de Bicicleta se llaman cadencia, velocidad y velocidad y todos los


datos son de tipo entero (int). La palabra reservada public identifica a estos atributos como
miembros pblicos, accesibles por cualquier objeto que pueda acceder a la clase.

Modificadores de acceso
El primer modificador utilizado (el de ms a la izquierda) permite controlar lo que otras clases
tienen acceso a los atributos. Por el momento slo se considerarn public y private (otros
modificadores de acceso se discutirn ms adelante):

modificador public, el atributo es accesible desde todas las clases.


modificador private, el atributo es accesible slo dentro de su propia clase.

De acuerdo con el concepto de encapsulacin, es comn que los atributos sean declarados
como privados (private). Esto significa que slo se puede acceder directamente desde la
clase Bicicleta. Sin embargo necesitamos tener acceso a estos valores. Esto se puede
lograr indirectamente, mediante la inclusin de mtodos pblicos que devuelven y establecen
los valores de los atributos por nosotros:
public class Bicicleta {
private int cadencia;
private int velocidad;
private int desplazamianto;
public Bicicleta(int cadenciaInicial, int desplazamiantoInicial,
int velocidadInicial) {
velocidad = velocidadInicial;
cadencia = cadenciaInicial;
desplazamianto = desplazamiantoInicial;
}
public int obtenerCadencia() { return cadencia; }
public void establecerCadencia(int nuevoValor) {
cadencia = nuevoValor;
}
public int obtenerVelocidad() { return velocidad; }
public void establecerVelocidad(int nuevoValor) {
velocidad = nuevoValor;
}
public int obtenerDesplazamiento() { return desplazamianto; }

public void frenar(int decremento) {


desplazamianto -= decremento;
}
public void acelerar(int incremento) {
desplazamianto += incremento;
}
}

Tipos
Todas las variables deben tener un tipo. Se pueden utilizar tipos primitivos como int, float,
boolean, etc., o se pueden utilizar tipos de referencia, tales como cadenas, arreglos u
objetos.

Nombres de variables
Todas las variables, ya sean atributos, variables locales o parmetros, siguen las siguientes
reglas y convenciones:
Los nombres de las variables distinguen entre maysculas y minsculas. El
nombre de una variable puede ser una secuencia de letras y dgitos de longitud
ilimitada, comenzando con una letra, el signo de pesos ($) o el carcter de subrayado
(_). Sin embargo, la convencin es comenzar los nombres de las variables siempre con
una letra, no con $ o _. Adems, por convencin, el carcter $ no se utiliza en absoluto.
El espacio en blanco no est permitido.
Los siguientes caracteres pueden ser letras, nmeros, signos de pesos o
caracteres de subrayado. Las convenciones (y el sentido comn) tambin aplican para
esta regla. Al elegir un nombre para las variables se deben utilizar palabras completas
en lugar de abreviaturas crpticas. Si se hace as, el cdigo ser ms fcil de leer y
entender. En muchos casos tambin har que el cdigo sea autodocumentado: los
atributos cadencia, velocidad y desplazamiento son mucho ms intuitivos que
las versiones abreviadas c, v y d. Tambin hay que tener en cuenta que el nombre que
se elija no debe ser una palabra reservada.
Si el nombre elegido se compone de una sola palabra, sta se debe escribir en
minsculas. Si se trata de ms de una palabra, se debe escribir en mayscula la
primera letra de cada palabra subsiguiente. Los nombres obtenerVelocidad y
establecerVelocidad son dos ejemplos de esta convencin. Si la variable almacena
un valor constante, como static final int NUM_VELOCIDADES = 6, la
convencin cambia un poco, escribiendo en maysculas todas las letras y separando
las palabras siguientes con el carcter de subrayado. Por convencin, el carcter de
subrayado no se utiliza en otros lugares.

Debemos tener en cuenta que las mismas reglas y convenciones se utilizan para los nombres
de los mtodos y de las clases, con excepcin de que

la primera letra del nombre de una clase debe ser escrita en mayscula y
la primera (o nica) palabra del nombre de un mtodo debe ser un verbo.

Definicin de mtodos
El siguiente es un ejemplo de una declaracin tpica de un mtodo:
public double calcularRespuesta(doble envergadura,
int numeroDeMotores,
double longitud,
double pesoBruto) {
// aqu se hace el clculo
}
Los nicos elementos necesarios en una declaracin de un mtodo son el tipo de dato que
devuelve el mtodo, su nombre, un par de parntesis () y un cuerpo entre llaves {}.
En general, las declaraciones de los mtodos tienen seis componentes, en este orden:
1. Modificadores, como public, private y otros que estudiaremos despus.
2. El tipo de dato del valor devuelto por el mtodo o void si el mtodo no devuelve
ningn valor.
3. El nombre del mtodo, en donde aplican las reglas para los nombres de los
atributos, pero la convencin es un poco diferente.
4. Una lista separada por comas de los parmetros de entrada, precedida por sus
tipos de datos, entre parntesis (). Si no hay parmetros, deben utilizar los parntesis
vacos.
5. Una lista de excepciones, que probablemente no estudiaremos en este curso.
6. El cuerpo del mtodo, encerrado entre llaves, que incluye la declaracin de las
variables locales.
Definicin: La declaracin de un mtodo comprende dos componentes: el nombre del mtodo
y los tipos de parmetros. A esto se le conoce como la firma del mtodo.
La firma del mtodo declarado anteriormente es:
calcularRespuesta(doble, int, double, doble)

Nombrar a un mtodo
A pesar de el nombre de un mtodo puede ser cualquier identificador legal, las convenciones
de cdigo restringen los nombres de los mtodos. Por convencin, los nombres de los mtodos
deben ser un verbo en minsculas o un nombre de varias palabra que comienza con un verbo
en minsculas, seguido de adjetivos, sustantivos, etc. En el caso de los nombres de varias
palabras, la primera letra de la segunda y las dems palabras debe ser mayscula. Los
siguientes son algunos ejemplos:
ejecutar
obtenerDatosFinales
compararCon
establecerX
estaVacia
Por lo general, un mtodo tiene un nombre nico dentro de su clase. Sin embargo, un mtodo
podra tener el mismo nombre que otros mtodos debido a la sobrecarga de mtodos.

Mtodos con sobrecarga


Java soporta sobrecarga de mtodos y puede distinguir los mtodos con firmas de mtodos
diferentes. Esto significa que los mtodos de una clase pueden tener el mismo nombre si tienen
distintas listas de parmetros.
Supongamos que tenemos una clase que puede utilizar caligrafa para dibujar varios tipos de
datos (cadenas, enteros, etc.) y que contiene un mtodo para dibujar de cada tipo de dato.
Sera engorroso usar un nombre diferente para cada mtodo, por ejemplo, dibujarCadena,
dibujarEntero, dibujarFlotante y as sucesivamente. En Java se puede utilizar el
mismo nombre para todos los mtodos de dibujo, pero se debe pasar una lista de argumentos
diferentes para cada mtodo. As, la clase de dibujo de datos podra declarar cuatro mtodos
llamados dibujar, cada uno de los cuales tiene una lista de parmetros diferente.
public class ArtistaDeDatos {
...
public void dibujar(String s) {
...
}
public void dibujar(int i) {
...
}
public void dibujar(double f) {
...
}

public void dibujar(int i, double f) {


...
}
}
Los mtodos con sobrecarga se diferencian por el nmero y el tipo de los argumentos que se
pasan al mtodo. En el cdigo de ejemplo, dibujar(String s) y dibujar(int i) son
mtodos distintos y nicos, ya que requieren distintos tipos de argumentos.
No se puede declarar ms de un mtodo con el mismo nombre y el mismo nmero y tipo de
argumentos, ya que el compilador no puede distinguirlos.
El compilador no considera el tipo de dato devuelto al diferenciar los mtodos, por lo que no se
pueden declarar dos mtodos con la misma firma, incluso si tienen un tipo de dato devuelto
diferente.

Definicin de constructores
Una clase contiene constructores que se invocan para crear objetos del modelo de la clase. La
declaracin de constructores es parecida a la declaracin de mtodos, excepto que se utiliza el
nombre de la clase y no devuelve ningn tipo de dato. Por ejemplo, Bicicleta tiene un
constructor:
public Bicicleta(int cadenciaInicial, int desplazamientoInicial,
int velocidadInicial) {
velocidad = velocidadInicial;
cadencia = cadenciaInicial;
desplazamiento = desplazamientoInicial;
}
Para crear un nuevo objeto de Bicicleta llamado miBicicleta, un constructor es llamado
por el operador new:
Bicicleta miBicicleta = new Bicicleta(30, 0, 8);
new Bicicleta (30, 0, 8) crea un espacio en la memoria para el objeto e inicializa sus
atributos.
Aunque Bicicleta slo tiene un constructor, podra tener otros, incluyendo un constructor sin
argumentos:
public Bicicleta() {
velocidad = 1;
cadencia = 10;

desplazamiento = 0;
}
Bicicleta tuBicicleta = new Bicicleta(); llama al constructor sin argumentos para
crear un nuevo objeto Bicicleta llamado tuBicicleta.
Ambos constructores podran haber sido declarado en Bicicleta porque tienen diferentes
listas de argumentos. Al igual que con los mtodos, Java diferencia constructores sobre la base
del nmero de argumentos en la lista y sus tipos. No se pueden escribir dos constructores que
tienen el mismo nmero y tipo de argumentos en la misma clase, porque Java no sera capaz
de distinguirlos. Si esto se hace, provocara un error en tiempo de compilacin.
No es necesario escribir un constructor para la clase, pero hay que tener cuidado al hacer esto.
El compilador proporciona por defecto un constructor sin argumentos para cualquier clase sin
constructores. Este constructor por defecto llama al constructor sin argumentos de la
superclase. En esta situacin, el compilador enviar un mensaje de error si la superclase no
tiene un constructor sin argumentos, por lo que se debe comprobar que si lo tenga. Si la clase
no tiene superclase explcita, entonces tiene una superclase implcita de Object, la cual si
tiene un constructor sin argumentos.
Se puede utilizar el constructor de una superclase. La clase BicicletaDeMontaa fue lo que
hizo. Se pueden utilizar modificadores de acceso en la declaracin de un constructor para
controlar cules otras clases pueden llamar al constructor.
Nota: Si otra clase no puede llamar al constructor de MiClase, no puede crear directamente
objetos MiClase.

Pasar informacin a un mtodo o constructor


La declaracin de un mtodo o un constructor define el nmero y el tipo de argumentos para
ese mtodo o constructor. Por ejemplo, el siguiente es un mtodo que calcula los pagos
mensuales de un prstamo hipotecario, basado en la cantidad del prstamo, la tasa de inters,
la duracin del prstamo (cantidad de perodos) y el valor futuro del prstamo:
public double calcularPago(double prestamo, double tasa,
double valorFuturo, int numPeriodos) {
double interes = tasa / 100.0;
double parcial = Math.pow((1 + interes), -numPeriodos);
double denominador = (1 - parcial) / interes;
double respuesta = (-prestamo / denominador)
- ((valorFuturo * parcial) / denominador);
return respuesta;
}

Este mtodo tiene cuatro parmetros: el monto del prstamo, la tasa de inters, el valor futuro y
el nmero de perodos. Los tres primeros son nmeros de doble precisin y el cuarto es un
nmero entero. Los parmetros se utilizan en el cuerpo del mtodo y al tiempo de ejecucin
tomar los valores de los argumentos que se pasan.
Nota: Los parmetros se refieren a la lista de variables en una declaracin de mtodo. Los
argumentos son los valores reales que se pasan cuando se invoca el mtodo. Cuando se
invoca un mtodo, los argumentos utilizados deben coincidir con los parmetros de la
declaracin en el tipo y orden.

Tipos de parmetros
Se puede utilizar cualquier tipo de datos para un parmetro de un mtodo o constructor. Esto
incluye los tipos de datos primitivos, tales como dobles, flotantes y enteros, como se vio en el
mtodo calcularPago y tipos de datos de referencia, tales como objetos y arreglos.
El siguiente es un ejemplo de un mtodo que acepta un arreglo como argumento. En este
ejemplo, el mtodo crea un nuevo objeto Poligono y lo inicializa desde un arreglo de objetos
Punto (consideremos que Punto es una clase que representa una coordenada x, y):
public Poligono crearPoligonoDe (Punto[] esquinas) {
// el cuerpo del mtodo va aqu
}
Nota: Java no permite pasar mtodos a los mtodos, pero se puede pasar un objeto a un
mtodo y luego llamar a los mtodos del objeto.

Un nmero arbitrario de argumentos


Se puede utilizar el constructor varargs a pasar un nmero arbitrario de valores a un mtodo.
Se utiliza varargs cuando no se sabe cuntos argumentos de un determinado tipo sern
pasados al mtodo. Es un mtodo directo para crear un arreglo manualmente (el mtodo
anterior podra haber utilizado varargs en lugar de un arreglo).
Para utilizar varargs, se escribe una elipsis (...) despus del tipo del parmetro pasado, seguido
de un espacio y el nombre del parmetro. El mtodo entonces puede ser llamado con cualquier
nmero de parmetros, incluso ninguno.
public Poligono crearPoligonoDe(Punto... esquinas) {
int numeroDeLados = esquinas.length;
double cuadradoLado1, LongitudLado1;
cuadradoLado1 = (esquinas[1].x - esquinas[0].x)

*(esquinas[1].x - esquinas[0].x)
+ (esquinas[1].y - esquinas[0].y)
*(esquinas[1].y - esquinas[0].y);
LongitudLado1 = Math.sqrt(cuadradoLado1);
// sigue ms cdigo en el cuerpo del mtodo para crear
// y devolver un polgono que conecta los puntos
}
Se puede ver que, dentro del mtodo, esquinas se trata como un arreglo. El mtodo puede
ser llamado ya sea con un arreglo o con una secuencia de argumentos. En ambos casos, el
cdigo en el cuerpo del mtodo tratar el parmetro como un arreglo.

Los nombres de parmetros


Cuando se declara un parmetro a un mtodo o constructor, se debe proporcionar un nombre
para ese parmetro. Este nombre se utiliza en el cuerpo del mtodo para referirse al argumento
que se le pasa.
El nombre de un parmetro debe ser nico en su alcance. No puede ser el mismo que el
nombre de otro parmetro para el mismo mtodo o constructor y no puede ser el nombre de
una variable local en el mtodo o el constructor.
Un parmetro puede tener el mismo nombre que uno de los atributos de la clase. Si este es el
caso, el parmetro se dice que oscurece el atributo. Oscurecer atributos puede hacer que el
cdigo sea difcil de leer y es convencionalmente utilizado slo dentro de los constructores y los
mtodos que establecen un campo en particular. Por ejemplo, consideremos la siguiente clase
Crculo y su mtodo establecerOrigen:
public class Circulo {
private int x, y, radio;
public void establecerOrigen(int x, int y) {
...
}
}
La clase Circulo tiene tres atributos: x, y y radio. El mtodo establecerOrigen tiene dos
parmetros, cada uno de los cuales tiene el mismo nombre que uno de los atributos. Cada
parmetro del mtodo oscurece al atributo del mismo nombre. As, utilizando los nombres
simples x o y dentro del cuerpo del mtodo se refiere al parmetro, no al atributo. Para acceder
al atributo, se debe utilizar un nombre completo, lo cual se discutir ms adelante.

Pasando argumentos de tipos de datos primitivos


Los argumentos primitivos, como int o double, se pasan a los mtodos por valor. Esto
significa que cualquier cambio en los valores de los parmetros existen slo dentro del alcance

del mtodo. Cuando regresa el mtodo, los parmetros se han ido y cualquier cambio en ellos
se pierden. Este es un ejemplo:

public class PasaPrimitivosPorValor {


public static void main(String[] args) {
int x = 3;
// llama a pasaMetodo() con x como argumento
pasaMetodo(x);
// imprime x para saber si cambi su valor
System.out.println("Despus de llamar a pasaMetodo, x = "
+ x);
}
public static void pasaMetodo(int p) {
p = 10;
}
}
Cuando se ejecuta este programa, la salida es:
Despus de llamar pasaMetodo, x = 3

Pasando argumentos de tipo de datos de referencia


Los parmetros de tipo de datos de referencia, como los objetos, tambin se pasan a los
mtodos por valor. Esto significa que cuando el mtodo regresa, la referencia que se pasa al
mtodo todava hace referencia al mismo objeto de antes. Sin embargo, los valores de los
atributos del objeto se puede cambiar en el mtodo siempre y cuando tengan el nivel de acceso
adecuado.
Por ejemplo, consideremos un mtodo en una clase arbitraria que mueve objetos de tipo
Circulo:
public void mueveCirculo(Circulo circulo, int deltaX, int deltaY) {
// cdigo para mover el origen de circulo a x+deltaX, y+deltaY
circulo.establecerX(circulo.obtenerX() + deltaX);
circulo.establecerY(circulo.obtenerY() + deltaY);
// cdigo para asignar una nueva referencia a circulo

circulo = new Circulo(0, 0);


}
Supongamos que el mtodo se llama con estos argumentos:
mueveCirculo(miCirculo, 23, 56)
En el mtodo, circulo inicialmente se refiere a miCirculo. El mtodo cambia las
coordenadas x e y del objeto que referencia circulo (es decir, miCirculo) por 23 y 56,
respectivamente. Estos cambios persisten cuando el mtodo regresa. Entonces se le asigna a
circulo una nueva referencia Circulo con x = 0 e y = 0. Sin embargo, esta reasignacin
no tiene permanencia, ya que la peticin fue aprobada en trminos de valor y no se puede
cambiar. En el mtodo, el objeto apuntado por el crculo ha cambiado, pero, cuando el mtodo
regresa, miCirculo todava hace referencia al mismo objeto Circulo que llam al mtodo.

Devolver un valor desde un mtodo


Un mtodo regresa al cdigo que lo llam cuando

completa todos las instrucciones en el mtodo,


llega a una sentencia return o
se produce una excepcin,

lo que ocurra primero.


El tipo de dato que se devuelve se declara junto con el mtodo. Dentro del cuerpo del mtodo,
se utiliza la sentencia return para devolver el valor.
Cualquier mtodo declarado void no devuelve un valor. ste no necesita contener la
instruccin return, aunque puede tenerla. En tal caso, una instruccin de retorno se puede
utilizar para ramificarse de un bloque de control de flujo y salir del mtodo y se utiliza
simplemente como:
return;
Si se intenta devolver un valor desde un mtodo que se declar void, se obtendr un error de
compilacin.
Cualquier mtodo que no se declarada void debe contener una sentencia return con un
valor de retorno correspondiente, de la forma:
return valorADevolver;

El tipo de dato del valor que se devuelve debe coincidir con el del tipo declarado en el mtodo,
es decir, no se puede devolver un valor entero de un mtodo declarado para devolver un
booleano.
El siguiente mtodo obtenerArea() regresa un valor entero:
// mtodo para calcular el rea de un rectngulo
public int obtenerArea() {
return base * altura;
}
Este mtodo devuelve el entero que resulta de la expresin base * altura.
El mtodo anterior devuelve un tipo de dato primitivo (entero). Un mtodo tambin puede
devolver un tipo de dato de referencia. Por ejemplo, en un programa para manipular objetos
Bicicleta podramos tener un mtodo como este:

public Bicicleta verCualEsMasRapida(Bicicleta miBicicleta,


Bicicleta tuBicicleta,
Environment env) {
Bicicleta masRapida;
// cdigo para calcular cul de las dos bicicletas es ms
// rpida, dadas la velocidad y la cadencia de cada bicicleta
// y dadas las condiciones del ambiente (terreno y viento)
return masRapida;
}

Devolucin de una clase o interfaz


Cuando un mtodo utiliza el nombre de una clase como tipo de retorno, tal como lo hace
verCualEsMasRapida, la clase del tipo del objeto devuelto debe ser una subclase de o la
clase exacta de el tipo de dato devuelto. Supongamos que se tiene una jerarqua de clases en
la que NumeroImaginario es una subclase de java.lang.Number, que a su vez es una
subclase de java.lang.Object, como se ilustra en la Figura 1.
Ahora supongamos que tenemos declarado un mtodo que devuelve un Number:
public Number devuelveUnNumero() {
...
}
Figura 1. Jerarqua de clases: NumeroImaginario es subclase de java.lang.Number y sta es subclase de

java.lang.Object.

El mtodo devuelveUnNumero() puede devolver un NumeroImaginario pero no un


Object. NumeroImaginario es un Number porque es una subclase de Number. Sin
embargo, un Object no es necesariamente un Number, ya que podra ser un String o de
otro tipo.
Se puede reemplazar un mtodo y definirlo para devolver una subclase del mtodo original, por
ejemplo:
public NumeroImaginario devuelveUnNumero() {
...
}
Esta tcnica, llamada tipo de retorno covariante, significa que se permite que el tipo de dato
que se devuelve vare en la misma direccin que la subclase.
Nota: Tambin se pueden utilizar los nombres de las interfaces como tipos de dato de retorno.
En este caso, el objeto devuelto debe implementar la interfaz especificada.

Uso de la palabra clave this


Dentro de un mtodo o un constructor, this es una referencia al objeto actual, es decir, el
objeto cuyo mtodo o constructor se est llamando. Podemos referirnos a cualquier miembro
del objeto actual dentro de un mtodo o un constructor con this.

El uso de this con un atributo


La razn ms comn para el uso de la palabra clave this es porque el atributo est
oscurecido por un parmetro del mtodo o constructor.
Por ejemplo, la clase Punto se escribe as
public class Punto {

public int x = 0;
public int y = 0;
// constructor
public Punto(int a, int b) {
x = a;
y = b;
}
}
Pero podra haberse escrito de la siguiente forma
public class Punto {
public int x = 0;
public int y = 0;
// constructor
public Punto(int x, int y) {
this.x = x;
this.y = y;
}
}
Cada argumento del constructor oscurece a uno de los atributos del objeto, ya que dentro del
constructor x es una copia local del primer argumento del constructor. Para hacer referencia al
atributo x de Punto, el constructor debe utilizar this.x.

El uso de this con un constructor


Dentro de un constructor tambin se puede utilizar la palabra clave this para llamar a otro
constructor de la misma clase. A esto se le conoce como una llamada explcita de constructor.
La siguiente es una clase Rectangulo.
public class Rectangulo {
private int x, y;
private int base, altura;
public Rectangulo() {
this(0, 0, 0, 0);
}
public Rectangulo(int base, int altura) {
this(0, 0, base, altura);
}
public Rectangulo(int x, int y, int base, int altura) {

this.x = x;
this.y = y;
this.base = base;
this.altura = altura;
}
...
}
Esta clase contiene un conjunto de constructores. Cada constructor inicializa todas o algunas
de las variables del rectngulo. Los constructores proporcionan un valor por defecto para
cualquier variable cuyo valor inicial no es proporcionado por un argumento. Por ejemplo, el
constructor sin argumentos llama al constructor de cuatro argumentos con cuatro valores 0 y el
constructor de dos argumentos llama al constructor de cuatro argumentos con dos valores 0.
Como se explic anteriormente, el compilador determina cul constructor se llama basndose
en el nmero y el tipo de argumentos.
Si est presente, la invocacin a otro constructor debe ser la primera lnea en el constructor.

Control de acceso a miembros de una clase


Los modificadores de nivel acceso determinan si otras clases pueden utilizar un atributo
especfico o invocar un mtodo en particular. Existen dos niveles de control de acceso:
A nivel superior, public o privado en el paquete (sin modificador explcito).
A nivel de miembro, public, private, protected o privado en el paquete (sin
modificador explcito).
Una clase puede ser declarada con el modificador public, en cuyo caso esa clase es visible a
todas las clases en todas partes. Si una clase no tiene ningn modificador (que es por defecto,
tambin conocido como privada en el paquete), es visible slo dentro de su propio paquete (los
paquetes son grupos de clases relacionadas).
A nivel de miembro, tambin se puede usar el modificador public o sin modificador (privado
en el paquete) as como con clases de nivel superior y con el mismo significado. Hay dos
modificadores de acceso adicionales para los miembros: private y protected. El
modificador private especifica que el elemento slo se puede acceder en su propia clase. El
modificador protected especifica que el miembro slo se puede acceder dentro de su propio
paquete (como con el privado en el paquete) y, adems, por una subclase de la clase en otro
paquete.
La tabla siguiente muestra el acceso a los miembros permitidos por cada modificador.
Modificador

Clase

Paquete

Subclase

Mundo

public

Si

Si

Si

Si

protected

Si

Si

Si

No

sin modificador

Si

Si

No

No

private

Si

No

No

No

La primera columna indica si la clase en s tiene acceso al miembro definido por el nivel de
acceso. Como se puede ver, una clase siempre tiene acceso a sus propios miembros. La
segunda columna indica si las clases en el mismo paquete que la clase (independientemente
de su ascendencia) tienen acceso al miembro. La tercera columna indica si las subclases de la
clase (declaradas fuera de este paquete) tienen acceso al miembro. La cuarta columna indica si
todas las clases tienen acceso al miembro.
Los niveles de acceso afectan de dos maneras. En primer lugar, cuando se utilizan clases que
vienen de otra fuente, como las clases de la plataforma Java, los niveles de acceso determinan
cules miembros de esas clases pueden usar las clases propias. En segundo lugar, cuando se
escribe una clase se necesita decidir qu nivel de acceso tendr cada variable y cada mtodo
en la clase.
Veamos un ejemplo con una coleccin de clases y cmo afectan los niveles de acceso a la
visibilidad. La Figura 2 muestra cuatro clases y cmo se relacionan.
Figura 2. Relacin entre cuatro clases distribuidas en dos paquetes.

La siguiente tabla muestra en dnde son visibles los miembros de la clase alfa para cada uno
de los modificadores de acceso que pueden ser aplicados a ellos.
Alfa

Beta

AlfaSub

Gama

public

Si

Si

Si

Si

protected

Si

Si

Si

No

Modificador

sin modificador

Si

Si

No

No

private

Si

No

No

No

Eleccin de nivel de acceso: Si otros programadores utilizan la clase, requerimos asegurar


que no sucedan errores por mal uso. Los niveles de acceso nos pueden ayudar a lograr esto.
Utilizar el nivel de acceso ms restrictivo que tiene sentido para un miembro en
particular. Utilizar private a menos que haya una buena razn para no hacerlo.
Evitar los atributos public, excepto para las constantes. Los atributos pblicas
tienden a vincularse con una aplicacin en particular y limita la flexibilidad al cambio el
cdigo.

Entendiendo a los miembros de instancia y de clase


En esta seccin, se discute el uso de la palabra clave static para crear campos y mtodos
que pertenecen a la clase, en lugar de a una instancia de la clase.

Variables de clase
Cuando un nmero de objetos se crean a partir del modelo de una misma clase, cada uno tiene
sus propias copias distintas de las variables de instancia. En el caso de la clase Bicicleta,
las variables de instancia son cadencia, velocidad y desplazamiento. Cada objeto
Bicicleta tiene sus propios valores para estas variables, almacenados en ubicaciones de
memoria diferentes.
En ocasiones requerimos tener variables que son comunes a todos los objetos. Esto se logra
con el modificador static. Los atributos que tienen el modificador static en la declaracin
se llaman atributos estticos o variables de clase. stos estn asociados con la clase y no con
el objeto. Cada instancia de la clase comparte una variable de clase, que est en una ubicacin
fija en la memoria. Cualquier objeto puede cambiar el valor de una variable de clase, pero las
variables de clase tambin pueden ser manipuladas sin necesidad de crear una instancia de la
clase.
Por ejemplo, supongamos que se desea crear una serie de objetos Bicicleta y asignar a
cada uno un nmero de serie, comenzando con 1 para el primer objeto. Este nmero de
identificacin (ID) es nico para cada objeto y por lo tanto es una variable de instancia. Al
mismo tiempo, se necesita un atributo para mantener un seguimiento de cuntos objetos se
han creado de Bicicleta y as saber qu ID se asigna al siguiente objeto. Tal atributo no est
relacionado con ningn objeto individual, sino a la clase en su conjunto. Para ello se necesita
una variable de clase, numeroDeBicicletas:
public class Bicicleta {
private int cadencia;

private int velocidad;


private int desplazamiento;
// se agrega una variable de instancia para el ID del objeto
private int id;
// se agrega una variable de clase para el nmero de objetos
// Bicicleta que han sido instanciados
private static int numeroDeBicicletas = 0;
...
}
Las variables de clase se referencian por el nombre de la clase en s, es decir
Bicicleta.numeroDeBicicletas
Esto deja en claro que son variables de clase.
Nota: Tambin se puede hacer referencia a los campos estticos mediante una referencia de
objeto, es decir
miBicicleta.numeroDeBicicletas
pero esto no se recomienda debido a que no quede claro que son variables de clase.
Se puede utilizar el constructor de Bicicleta para establecer la variable de instancia id e
incrementar la variable de clase numeroDeBicicletas:

public class Bicicleta {


private
private
private
private
private

int cadencia;
int velocidad;
int desplazamiento;
int id;
static int numeroDeBicicletas = 0;

public Bicicleta(int cadenciaInicial, int desplazamientoInicial,


int velocidadInicial){
velocidad = velocidadInicial;
cadencia = cadenciaInicial;

desplazamiento = desplazamientoInicial;
// se incrementa el nmero de Bicicletas y se asigna un id
id = ++numeroDeBicicletas;
}
// nuevo mtodo para devolver el ID de la variable de instancia
public int obtenerID() {
return id;
}
...
}

Mtodos de clase
Java soporta mtodos estticos y variables estticas. Estos mtodos, que tienen el modificador
static en sus declaraciones, se debe invocar con el nombre de la clase, sin la necesidad de
crear una instancia de la clase, por ejemplo
NombreDeLaClase.nombreDelMetodo(args)
Nota: Tambin se puede hacer referencia a mtodos estticos con una referencia de objeto,
por ejemplo
NombreDeLaInstancia.nombreDelMetodo(args)
pero esto no se recomienda debido a que no queda claro que son mtodos de clase.
Un uso comn de los mtodos estticos es tener acceso a los atributos estticos. Por ejemplo,
podramos aadir un mtodo esttico de la clase Bicicleta para acceder al atributo esttico
numeroDeBicicletas:
public static int obtenernNumeroDeBicicletas() {
return numeroDeBicicletas;
}
No todas las combinaciones de variables de instancia y de clase y mtodos estn permitidos:
Los mtodos de instancia pueden acceder a las variables y a los mtodos de
instancia directamente.
Los mtodos de instancia pueden acceder a las variables y mtodos de clase
directamente.
Los mtodos de clase puede acceder a las variables y mtodos de clase
directamente.
Los mtodos de clase no pueden acceder a las variables ni a los mtodos de

instancia directamente, se debe utilizar una referencia de objeto. Adems, los mtodos
de clase no pueden utilizar la palabra clave this ya que no hay ninguna instancia para
hacer referencia a this.

Constantes
El modificador static, en combinacin con el modificador final, se utiliza tambin para
definir constantes. El modificador final indica que el valor de este atributo no se puede
modificar. Por ejemplo, la siguiente declaracin de variable define una constante llamada PI,
cuyo valor es una aproximacin de pi (la relacin entre la circunferencia de un crculo y su
dimetro):
static final double PI = 3.141592653589793;
Las constantes definidas de esta manera no pueden ser reasignadas y surgir un error al
tiempo de compilacin si el programa trata de hacerlo. Por convencin, los nombres de los
valores constantes se escriben en maysculas. Si el nombre est compuesto por ms de una
palabra, las palabras estn separadas por un guin bajo (_).
Nota: Si un tipo de dato primitivo o una cadena se define como una constante y el valor es
conocido en tiempo de compilacin, el compilador reemplaza el nombre de la constante en
todas partes en el cdigo con su valor. A sta se le conoce como una constante de tiempo de
compilacin. Si el valor de la constante en el mundo exterior cambia (por ejemplo, si est
demostrado que pi en realidad debera ser 3.975), se tendrn que volver a compilar las clases
que utilizan esta constante para obtener el valor actual.

La clase Bicicleta
Despus de que todas las modificaciones realizadas en esta seccin, la clase Bicicleta
ahora es:
public class Bicicleta {
private int cadencia;
private int velocidad;
private int desplazamiento;
private int id;
private static int numeroDeBicicletas = 0;
public Bicicleta(int cadenciaInicial, int desplazamientoInicial,
int velocidadInicial){
velocidad = velocidadInicial;

cadencia = cadenciaInicial;
desplazamiento = desplazamientoInicial;
id = ++numeroDeBicicletas;
}
public int obtenerID() { return id; }
public static int obtenernNumeroDeBicicletas() {
return numeroDeBicicletas;
}
public int obtenerCadencia() { return cadencia; }
public void establecerCadencia(int nuevoValor) {
cadencia = nuevoValor;
}
public int obtenerVelocidad() { return velocidad; }
public void establecerVelocidad(int nuevoValor) {
velocidad = nuevoValor;
}
public int obtenerDesplazamiento() { return desplazamianto; }
public void frenar(int decremento) {
desplazamianto -= decremento;
}
public void acelerar(int incremento) {
desplazamianto += incremento;
}
}

Inicializacin de atributos
Como hemos visto, podemos definir un valor inicial para un atributo en su declaracin
public class BedAndBreakfast {
public static int capacidad = 10;
private boolean lleno = false;

// inicializado en 10
// inicializado en false

}
Esto funciona bien cuando el valor de inicializacin est disponible y la inicializacin se puede

poner en una lnea. Sin embargo, esta forma de inicializacin tiene limitaciones debido a su
simplicidad. Si la inicializacin requiere alguna lgica (por ejemplo, manejo de errores o un ciclo
for para llenar un arreglo complejo), la asignacin simple es inadecuada. Las variables de
instancia se pueden inicializar en constructores, en donde se puede utilizar el manejo de
errores u otra lgica. Para proporcionar la misma capacidad para las variables de clase, Java
incluye bloques estticos de inicializacin.
Nota: No es necesario declarar atributos al comienzo de la definicin de una clase, aunque
esta es la prctica ms comn. Slo es necesario que se declare y se inicialice antes de ser
utilizados.

Bloques estticos de inicializacin


Un bloque esttico de inicializacin es un bloque normal de cdigo entre llaves ({}) y precedido
por la palabra clave static. El siguiente es un ejemplo:
static {
// code necesario para la inicializacin
}

Una clase puede tener cualquier nmero de bloques estticos de inicializacin y pueden
aparecer en cualquier parte del cuerpo de la clase. El sistema de ejecucin garantiza que los
bloques estticos de inicializacin sean llamados en el orden en que aparecen en el cdigo
fuente.
Hay una alternativa a los bloques estticos, se puede escribir un mtodo esttico privado:
class LoQueSea {
public static tipoVar miVar = inicializarVariableDeClase();
private static tipoVar inicializarVariableDeClase() {
// cdigo de inicializacin
}
}
La ventaja de los mtodos estticos privados es que se pueden reutilizar despus si se
necesita inicializar la variable de clase.

Inicializacin de los miembros de instancia


Normalmente se debera colocar el cdigo para inicializar una variable de instancia en un

constructor. Hay dos alternativas para usar un constructor para inicializar las variables de
instancia: bloques de inicializador y mtodos finales.
Los bloques inicializadores de variables de instancia se parecen a los bloques estticos
inicializadores, pero sin la palabra clave static:
{
// cdigo necesario para la inicializacin
}
El compilador de Java copia los bloques inicializadores en cada constructor. Por lo tanto, este
enfoque puede ser usado para compartir un bloque de cdigo entre varios constructores.
Un mtodo final no se puede reemplazar en una subclase. Este tema se trata ms adelante.
Abajo se presenta un ejemplo del uso de un mtodo final para inicializar una variable de
instancia:

class LoQueSea {
public static tipoVar miVar = inicializarVariableDeClase();
protected final tipoVar inicializarVariableDeClase() {
// cdigo de inicializacin
}
}
Esto es especialmente til si las subclases posiblemente requieran reutilizar el mtodo de
inicializacin. El mtodo es final porque llamar a mtodos no finales durante la
inicializacin de instancia puede causar problemas.

Preguntas y Ejercicios
Preguntas
1. Considera la siguiente clase:
public class IdentificaLasPartes {
public static int x = 7;
public int y = 3;
}
a. Cules son las variables de clase?
b. Cules son las variables de instancia?
c. Cul es la salida del cdigo siguiente?

IdentificaLasPartes a = new IdentificaLasPartes();


IdentificaLasPartes b = new IdentificaLasPartes();
a.y = 5;
b.y = 6;
a.x = 1;
b.x = 2;
System.out.println("a.y = " + a.y);
System.out.println("b.y = " + b.y);
System.out.println("a.x = " + a.x);
System.out.println("b.x = " + b.x);
System.out.println("IdentificaLasPartes.x = "
+ IdentificaLasPartes.x);

Ejercicios
1. Escribe una clase cuyas instancias representan una sola carta de un mazo
de cartas. Las cartas tienen dos propiedades distintivas: orden y conjunto.
Sugerencia: Se puede utilizar la instruccin assert para revisar las asignaciones.
Si escribimos:
assert (expresin booleana para realizar una prueba);
Si la expresin booleana es falsa, se recibir un mensaje de error. Por ejemplo,
assert aCadena(As) == "As";
debe devolver true, por lo que no habr ningn mensaje de error.
Si se utiliza la instruccin assert, se debe ejecutar el programa con la bandera
ea:
java -ea TuPrograma.class
2. Escribe una clase cuyas instancias representan un mazo completo de
cartas.
3. Escribe un pequeo programa para poner a prueba tus clases de carta y
mazo. El programa puede ser tan simple como la creacin de un mazo de cartas y
mostrar sus cartas.

Você também pode gostar