Similarmente a la implementación de una clase, la implementación de un método consiste en dos
partes, la declaración y el cuerpo del método.
declaracióndeMétodo {
cuerpodeMétodo
}
La Declaración de Método
Una declaración de método proporciona mucha información sobre el método al
compilador, al sistema en tiempo de ejecución y a otras clases y objetos. Junto con el
nombre del método, la declaración lleva información como el tipo de retorno del
método, el número y el tipo de los argumentos necesarios, y qué otras clases y objetos
pueden llamar al método.
Los únicos elementos necesarios una declaración de método son el nombre y el tipo de
retorno del método.
Por ejemplo, el código siguiente declara un método llamado
estaVacio() en la clase Pila que devuelve un valor booleano (true o false):
class Pila {
. . .
boolean estaVacio() {
. . .
}
}
Devolver un Valor desde un Método
Java necesita que un método declare el tipo de dato del valor que devuelve. Si un
método no devuelve ningún valor, debe ser declarado para devolver void (nulo).
Los métodos pueden devolver tipos de datos primitivos o tipos de datos de referencia. El
método estaVacio() de la clase Pila devuelve un tipo de dato primitivo, un valor
booleano:
class Pila {
static final int PILA_VACIA = -1;
Object[] stackelements;
int topelement = PILA_VACIA;
. . .
boolean estaVacio() {
if (topelement == PILA_VACIA)
return true;
else
return false;
}
}
Sin embargo, el método pop de la clase PILA devuelve un tipo de dato de referencia: un
objeto.
class Pila {
static final int PILA_VACIA = -1;
Object[] stackelements;
int topelement = PILA_VACIA;
. . .
Object pop() {
if (topelement == PILA_VACIA)
return null;
else {
return stackelements[topelement--];
}
}
}
Los métodos utilizan el operador return para devolver un valor. Todo método que no
sea declarado como void debe contener una sentencia return.
El tipo de dato del valor devuelto por la sentencia return debe corresponder con el tipo
de dato que el método tiene que devolver; no se puede devolver un objeto desde un
método que fue declarado para devolver un entero.
Cuando se devuelva un objeto, el tipo de dato del objeto devuelto debe ser una
subclase o la clase exacta indicada. Cuando se devuelva un tipo interface, el objeto
retornado debe implementar el interface especificado.
Un Nombre de Método
Un nombre de método puede ser cualquier indentificador legal en Java. Existen tres
casos especiales a tener en cuenta con los nombres de métodos:
Java soporta la sobrecarga de métodos, por eso varios métodos pueden compartir
el mismo nombre. Por ejemplo, supon que se ha escrito una clase que puede
proporcionar varios tipos de datos (cadenas, enteros, etc...) en un área de dibujo.
Se podría escribir un método que supiera como tratar a cada tipo de dato. En otros
lenguajes, se tendría que pensar un nombre distinto para cada uno de los
métodos. dibujaCadena(), dibujaEntero, etc... En Java, se puede utilizar el
mismo nombre para todos los métodos pasándole un tipo de parámetro diferente a
cada uno de los métodos. Entonces en la clase de dibujo, se podrán declarar tres
métodos llamados draw<() y que cada uno aceptara un tipo de parámetro
diferente:
class DibujodeDatos {
void draw(String s) {
. . .
}
void draw(int i) {
. . .
}
void draw(float f) {
. . .
}
}
Nota: La información que hay dentro de los paréntesis de la declaración son los
argumentos del método. Los argumentos se cubren en la siguiente página: Pasar
Información a un Método.
Los métodos son diferenciados por el compilador basándose en el número y tipo de
sus argumentos. Así draw(String s)y draw(int i) son métodos distintos y únicos.
No se puede declarar un método con la misma firma: draw(String s)y
draw(String t) son idénticos y darán un error del compilador.
Habrás observado que los métodos sobrecargados deben devolver el mismo tipo de
1.
dato, por eso void draw(String s) y int draw(String t) declarados en la misma
clase producirán un error en tiempo de compilación.
Todo método cuyo nombre sea igual que el de su clase es un constructor y tiene
una tarea especial que realizar. Los constructores se utilizan para inicializar un
objeto nuevo del tipo de la clase. Los constructores sólo pueden ser llamados con
el operador new. Para aprender cómo escribir un constructor, puedes ver Escribir
un Método Constructor.
2.
Una clase puede sobreescribir un método de sus superclases. El método que
sobreescribe debe tener el mismo, nombre, tipo de retorno y lista de parámetros
que el método al que ha sobreescrito. Sobreescribir Métodos te enseñará como
sobreescribir los métodos de una superclase.
3.
Caractersiticas Avanzadas de la Declaración de Métodos
Junto con los dos elementos necesarios, una declaración de método puede contener
otros elementos. Estos elementos declaran los argumentos aceptados por el método, si
el método es un método de clase, etc...
Juntándolo todo, una declaración de método se parecería a esto:
[especificadordeAcceso] [static] [abstract] [final] [native] [synchronized]
tipodeRetorno nombredelMétodo ([listadeparámetros]) [throws listadeExcepciones]
Cada uno de estos elementos de una declaración se cubre en alguna parte de este
tutorial.
Pasar Información a un Método.
Cuando se escribe un método, se declara el número y tipo de los argumentos requeridos por ese
método. Esto se hace en la firma del método. Por ejemplo, el siguiente método calcula el pago
mensual de una hipoteca basándose en la cantidad prestada, el interés, la duración de la hipoteca
(número de meses) y el valor futuro de la hipoteca (presumiblemente el valor futuro sea cero,
porque al final de la hipoteca, ya la habrás pagado):
double hipoteca(double cantidad, double interes, double valorFinal, int numPeriodos)
{
double I, parcial1, denominador, respuesta;
I = interes / 100.0;
parcial1 = Math.pow((1 + I), (0.0 - numPeriodos));
denominador = (1 - parcial1) / I;
respuestar = ((-1 * cantidad) / denominador) - ((valorFinal * parcial1) /
denominador);
return respuesta;
}
Este método toma cuatro argumentos: la cantidad prestada, el interés, el valor futuro y el número
de meses. Los tres primeros son números de coma flotante de doble precisión y el cuarto es un
entero.
Al igual que este método, el conjunto de argumentos de cualquier método es una lista de
declaraciones de varibales delimitadas por comas donde cada declaración de varibale es un par
tipo/nombre:
tipo nombre
Como has podido ver en el ejemplo anterior, sólo tienes que utilizar el nombre del argumento para
referirte al valor del argumento.
Tipos de Argumentos
En Java, se puede pasar como argumento a un método cualquier tipo de dato válido en
Java. Esto incluye tipos primitivos, como enteros, dobles, etc.. y tipos de referencia como
arrays, objetos, etc...
Aquí tienes un ejemplo de un constructor que acepta una array como argumento. En este
ejemplo el constructor inicializa un objeto Polygon a partir de una lista de puntos (Point es
una clase del paquete java.awt que representa una coordenada xy):
Polygon polygonFrom(Point[] listadePuntos) {
. . .
}
Al contrario que en otros lenguajes, no se puede pasar un método a un método Java. Pero
si se podría pasar un objeto a un método y luego llamar a los métodos del objeto.
Nombres de Argumentos
Cuando se declara un argumento para un método Java, se proporciona el nombre para ese
argumento. Este nombre es utilizado dento del cuerpo del método para referise al valor
del argumento.
Un argumento de un método puede tener el mismo nombre que una variable de la clase.
En este caso, se dice que el argumento oculta a la variable miembro. Normalmente los
argumentos que ocultan una variable miembro se utilizan en los constructores para
inicializar una clase. Por ejemplo, observa la clase Circle y su constructor:
class Circle {
int x, y, radius;
public Circle(int x, int y, int radius) {
. . .
}
}
La clase Circle tiene tres variables miembro x, y y radius. Ademñas, el constructor de la
clase Circle acepta tres argumentos cada uno de los cuales comparte el nombre con la
variable miembro para la que el argumento proporciona un valor inicial.
Los nombres de argumentos ocultan los nombres de las variables miembro. Por eso
utilizar x, y o radius dentro del cuerpo de la función, se refiere a los argumentos, no a las
variables miembro. Para acceder a las varibales miembro, se debe referenciarlas a través
de this--el objeto actual.
class Circle {
int x, y, radius;
public Circle(int x, int y, int radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
}
Los nombres de los argumentos de un método no pueden ser el mismo que el de otros
argumentos del mismo método, el nombre de cualquier variable local del método o el
nombre de cualquier parámetro a una clausula catch() dentro del mismo método.
Paso por Valor
En los métodos Java, los argumentos son pasados por valor. Cuando se le llama, el
método recibe el valor de la variable pasada. Cuando el argumento es de un tipo primitivo,
pasar por valor significa que el método no puede cambiar el valor. Cuando el argumento
es del tipo de referencia, pasar por valor significa que el método no puede cambiar el
objeto referenciado, pero si puede invocar a los métodos del objeto y puede modificar las
variables accesibles dentro del objeto.
Consideremos esta serie de sentencias Java que intentan recuperar el color actual de un
objeto Pen en una aplicación gráfica:
. . .
int r = -1, g = -1, b = -1;
pen.getRGBColor(r, g, b);
System.out.println("red = " + r + ", green = " + g + ", blue = " + b);
. . .
En el momento que se llama al método getRGBColor(), las variables r, g, y b tienen un
valor de -1. El llamador espera que el método getRGBColor() le devuelva los valores de
rojo, verde y azul para el color actual en las variables r, g, y b.
Sin embargo, el sistema Java pasa los valores de las variables(-1) al método
getRGBColor(); no una referencia a las variables r, g, y b. Con esto se podría visualizar
la llamada a getRGBColor() de esta forma: getRGBColor(-1, -1, -1).
Cuando el control pasa dentro del método getRGBColor(), los argumentos entran dentro
del ámbito (se les asigna espacio) y son inicializados a los valores pasados al método:
class Pen {
int valorRojo, valorVerde, valorAzul;
void getRGBColor(int rojo, int verde, int azul) {
// rojo, verde y azul han sido creados y sus valores son -1
. . .
}
}
Con esto getRGBColor() obtiene acceso a los valores de r, g, y b del llamador a tavés de
sus argumentos rojo, verde, y azul, respectivamente. El método obtiene su propia copia
de los valores para utilizarlos dentro del ámbito del método. Cualquier cambio realizado en
estas copias locales no seran reflejados en las variables originales del llamador.
Ahora veremos la implementación de getRGBColor() dentro de la clase Pen que
implicaba la firma de método anterior:
class Pen {
int valorRojo, valorVerde, valorAzul;
. . .
// Este método no trabaja como se espera
void getRGBColor(int rojo, int verde, int azul) {
rojo = valorRojo;
verde=valorVerde;
azul=valorAzul;
}
}
Este método no trabajará como se espera. Cuando el control llega a la sentencia println()
en el siguiente fragmento de código, los argumentos rojo, verde y azul de
getRGBColor() ya no existen. Por lo tanto las asignaciones realizadas dentro del método
no tendrán efecto; r, g, y b seguiran siendo igual a -1.
. . .
int r = -1, g = -1, b = -1;
pen.getRGBColor(r, g, b);
System.out.println("rojo = " + r + ", verde = " + g + ", azul = " + b);
. . .
El paso de las varibales por valor le ofrece alguna seguridad a los programadores: los
métodos no puede modificar de forma no intencionada una variable que está fuera de su
ámbito. Sin embargo, alguna vez se querrá que un método modifique alguno de sus
argumentos. El metodo getRGBColor() es un caso apropiado. El llamador quiere que el
método devuelva tres valores a través de sus argumentos. Sin embargo, el método no
puede modificar sus argumentos, y, además, un método sólo puede devolver un valor a
través de su valor de retorno. Entonces, ¿cómo puede un método devolver más de un
valor, o tener algún efecto (modificar algún valor) fuera de su ámbito?
Para que un método modifique un argumento, debe ser un tipo de referencia como un
objeto o un array. Los objetos y arrays también son pasados por valor, pero el valor de un
objeto es una referencia. Entonces el efecto es que los argumentos de tipos de referencia
son pasados por referencia. De aquí el nombre. Una referencia a un objeto es la dirección
del objeto en la memoria. Ahora, el argumento en el método se refiere a la misma
posición de memoria que el llamador.
Reescribamos el método getRGBColor() para que haga lo que queremos. Primero
introduzcamos un nuevo objeto RGBColor, que puede contener los valores de rojo, verde y
azul de un color en formato RGB:
class RGBColor {
public int rojo, verde, azul;;
}
Ahora podemos reescribir getRGBColor() para que acepte un objeto RGBColor como
argumento. El método getRGBColor() devuelve el color actual de lápiz, en los valores de
las variables miembro rojo, verde y azul de su argumento RGBColor:
class Pen {
int valorRojo, valorVerde, valorAzul;
void getRGBColor(RGBColor unColor) {
unColor.rojo = valorRojo;
unColor.verde = valorVerde;
unColor.azul = valorAzul;
}
}
Y finalmente, reescribimos la secuencia de llamada:
. . .
RGBColor penColor = new RGBColor();
pen.getRGBColor(penColor);
System.out.println("ojo = " + penColor.rojo + ", verde = " + penColor.verde + ",
azul = " + penColor.azul);
. . .
Las modificaciones realizadas al objeto RGBColor dentro del método getRGBColor()
afectan al objeto creado en la secuencia de llamada porque los nombres penColor (en la
secuencia de llamada) y unColor (en el método getRGBColor()) se refieren al mismo
objeto.
El Cuerpo del Método
En el siguiente ejemplo, el cuerpo de método para los métodos estaVacio() y
poner() están en negrita:
class Stack {
static final int PILA_VACIA = -1;
Object[] elementosPila;
int elementoSuperior = PILA_VACIA;
. . .
boolean estaVacio() {
if (elementoSuperior == PILA_VACIA)
return true;
else
return false;
}
Object poner() {
if (elementoSuperior == PILA_VACIA)
return null;
else {
return elementosPila[elementoSuperior--];
}
}
}
Junto a los elementos normales del lenguaje Java, se puede utilizar this en el
cuerpo del método para referirse a los miembros del objeto actual. El objeto actual
es el objeto del que uno de cuyos miembros está siendo llamado. También se
puede utilizar super para referirse a los miembros de la superclase que el objeto
actual haya ocultado mediante la sobreescritura. Un cuerpo de método también
puede contener declaraciones de variables que son locales de ese método.
this
Normalmente, dentro del cuerpo de un método de un objeto se puede
referir directamente a las variables miembros del objeto. Sin embargo,
algunas veces no se querrá tener ambiguedad sobre el nombre de la
variable miembro y uno de los argumentos del método que tengan el
mismo nombre.
Por ejemplo, el siguiente constructor de la clase HSBColor inicializa
alguna variable miembro de un objeto de acuerdo a los argumentos
pasados al constructor. Cada argumento del constructor tiene el mismo
nombre que la variable del objeto cuyo valor contiene el argumento.
class HSBColor {
int hue, saturacion, brillo;
HSBColor (int luminosidad, int saturacion, int brillo) {
this.luminosidad = luminosidad;
this.saturacion = saturacion;
this.brillo = brillo;
}
}
Se debe utilizar this en este constructor para evitar la embiguedad entre
el argumento luminosidad y la variable miembro luminosidad (y así
con el resto de los argumentos). Escribir luminosidad = luminosidad;
no tendría sentido. Los nombres de argumentos tienen mayor
precedencia y ocultan a los nombres de las variables miembro con el
mismo nombre. Para referirise a la variable miembro se debe hacer
explicitamente a través del objeto actual--this.
También se puede utilizar this para llamar a uno de los métodos del
objeto actual. Esto sólo es necesario si existe alguna ambigüedad con el
nombre del método y se utiliza para intentar hacer el código más claro.
super
Si el método oculta una de las variables miembro de la superclase, se
puede referir a la variable oculta utilizando super. De igual forma, si el
método sobreescribe uno de los métodos de la superclase, se puede
llamar al método sobreescrito a través de super.
Consideremos esta clase:
class MiClase {
boolean unaVariable;
void unMetodo() {
unaVariable = true;
}
}
y una subclase que oculta unaVariable y sobreescribe unMetodo():
class OtraClase extends MiClase {
boolean unaVariable;
void unMetodo() {
unaVariable = false;
super.unMetodo();
System.out.println(unaVariable);
System.out.println(super.unaVariable);
}
}
Primero unMetodo() selecciona unaVariable (una declarada en
OtraClase que oculta a la declarada en MiClase) a false. Luego
unMetodo() llama a su método sobreescrito con esta sentencia:
super.unMetodo();
Esto selecciona la versión oculta de unaVariable (la declarada en
MiClase) a true. Luego unMetodo muestra las dos versiones de
unaVariable con diferentes valores:
false
true
Variables Locales
Dentro del cuerpo de un método se puede declarar más variables para
usarlas dentro del método. Estas variables son variables locales y viven
sólo mientras el control permanezca dentro del método. Este método
declara un variable local i y la utiliza para operar sobre los elementos del
array.
Object encontrarObjetoEnArray(Object o, Object[] arrayDeObjetos) {
int i; // variable local
for (i = 0; i < arrayDeObjetos.length; i++) {
if (arrayDeObjetos[i] == o)
return o;
}
return null;
}
Después de que este método retorne, i ya no existirá más.
Leer más...
Mostrando entradas con la etiqueta basicos de java. Mostrar todas las entradas
Mostrando entradas con la etiqueta basicos de java. Mostrar todas las entradas
martes, 15 de septiembre de 2009
Declarar Clases
Ahora que ya sabemos como crear, utilizar y destruir objetos, es hora de aprender cómo escribir clases
de las que crear esos objetos.
Una clase es un proyecto o prototipo que se puede utilizar para crear muchos objetos. La implementación
de una clase comprende dos componentes: la declaración y el cuerpo de la clase:
DeclaraciónDeLaClase {
CuerpoDeLaClase
}
La Declaración de la Clase
Como mínimo, la declaración de una clase debe contener la palabra clave class y el nombre de
la clase que está definiendo. Así la declaración más sencilla de una clase se parecería a esto:
class NombredeClase {
. . .
}
Por ejemplo, esta clase declara una nueva clase llamada NumeroImaginario:
class NumeroImaginario {
. . .
}
Los nombres de las clases deben ser un identificador legal de Java y, por convención, deben
empezar por una letra mayúscula. Muchas veces, todo lo que se necesitará será una
declaración mínima. Sin embargo, la declaración de una clase puede decir más cosas sobre la
clase. Más especificamente, dentro de la declaración de la clase se puede:
l declarar cual es la superclase de la clase.
l listar los interfaces implementados por la clase
l declarar si la clase es pública, abstracta o final
Declarar la Superclase de la Clase
En Java, todas las clases tienen una superclase. Si no se especifica una superclase para una
clase, se asume que es la clase Object (declarada en java.lang). Entonces la superclase de
NumeroImaginario es Object porque la declaración no explicitó ninguna otra clase. Para
obtener más información sobre la clase Object, puede ver La clase Object.
Para especificar explícitamente la superclase de una clase, se debe poner la palabra clave
extends más el nombre de la superclase entre el nombre de la clase que se ha creado y el
corchete abierto que abre el cuerpo de la clase, así:
class NombredeClase extends NombredeSuperClase {
. . .
}
Por ejemplo, supon que quieres que la superclase de NumeroImaginario sea la clase Number
en vez de la clase Object. Se podróa escribir esto:
class NumeroImaginario extends Number {
. . .
}
Esto declara explícitamente que la clase Number es la superclase de NumeroImaginario. (La
clase Number es parte del paquete java.lang y es la base para los enteros, los números en
coma flotante y otros números).
Declarar que Number es la superclase de NumeroImaginario declara implícitamente que
NumeroImaginario es una subclase de Number. Una subclase hereda las variables y los
métodos de su superclase.
Crear una subclase puede ser tan sencillo como incluir la clausula extends en su declaración
de clase. Sin embargo, se tendrán que hacer otras provisiones en su código cuando se crea una
subclase, como sobreescribir métodos. Para obtener más información sobre la creacción de
subclases, puede ver Subclases, Superclases, y Herencia.
Listar los Interfaces Implementados por la Clase
Cuando se declara una clase, se puede especificar que interface, si lo hay, está implementado
por la clase. Pero, ¿Qué es un interface? Un interface declara un conjunto de métodos y
constantes sin especificar su implementación para ningún método. Cuando una clase exige la
implementación de un interface, debe proporcionar la implementación para todos los métodos
declarados en el interface.
Para declarar que una clase implementa uno o más interfaces, se debe utilizar la palabra clave
implements seguida por una lista de los interfaces implementados por la clase delimitada por
comas. Por ejemplo, imagina un interface llamado Aritmetico que define los métodos llamados
suma(), resta(), etc... La clase NumeroImaginario puede declarar que implementa el
interface Aritmetico de esta forma:
class NumeroImaginario extends Number implements Aritmetico {
. . .
}
se debe garantizar que propociona la implementación para los métodos suma(), resta() y
demás métodos declarados en el interface Aritmetico. Si en NumeroImaginario falta alguna
implementación de los métodos definidos en Aritmetico, el compilador mostrará un mensaje de
error y no compilará el programa:
nothing.java:5: class NumeroImaginario must be declared abstract. It does not define
java.lang.Number add(java.lang.Number, java.lang.Number) from interface Aritmetico.
class NumeroImaginario extends Number implements Aritmetico {
^
Por convención, la clausula implements sigue a la clausula extends si ésta existe.
Observa que las firmas de los métodos declarados en el interface Aritmetico deben
corresponder con las firmas de los métodos implementados en la clase NumeroImaginario.
Tienes más información sobre cómo crear y utilizar interfaces en Crear y Utilizar Interfaces.
Clases Public, Abstract, y Final
Se puede utilizar uno de estos tres modificadores en una declaración de clase para declarar que
esa clase es pública, abstracta o final. Los modificadores van delante de la palabra clave class
y son opcionales.
El modificador public declara que la clase puede ser utilizada por objetos que estén fuera del
paquete actual. Por defecto, una clase sólo puede ser utiliza por otras clases del mismo
paquete en el que están declaradas.
public class NumeroImaginario extends Number implements Aritmetico {
. . .
}
Por convención, cuando se utiliza la palabra public en una declaración de clase debemos
asegurarnos de que es el primer item de la declaración.
El modificador abstract declara que la clase es una clase abstracta. Una clase abstracta podría
contener métodos abstractos (métodos sin implementación). Una clase abstracta está diseñada
para ser una superclase y no puede ejemplarizarse. Para una discusión sobre las clases
abstractas y cómo escribirlas puedes ver Escribir Clases y Métodos Abstractos.
Utilizando el modificador final se puede declarar que una clase es final, que no puede tener
subclases. Existen (al menos) dos razones por las que se podría querer hacer esto: razones de
seguridad y razones de diseño. Para un mejor explicaión sobre las clases finales puedes ver
Escribir Clases y Métodos Finales.
Observa que no tiene sentido para una clase ser abstracta y final. En otras palabras, una clase
que contenga métodos no implementados no puede ser final. Intentar declarar una clase como
final y abstracta resultará en un error en tiempo de compilación.
Sumario de la Daclaración de una Clase
En suma, una declaración de clase se parecería a esto:
[ modificadores ] class NombredeClase [ extends NombredeSuperclase ]
[ implements NombredeInterface ] {
. . .
}
Los puntos entre [ y ] son opcionales. Una declaración de clase define los siguientes aspectos
de una clase:
l modificadores declaran si la clase es abstracta, pública o final.
l NombredeClase selecciona el nombre de la clase que está declarando
l NombredeSuperClase es el nombre de la superclase de NombredeClase
NombredeInterface es una lista delimitada por comas de los interfaces implementados
por NombredeClase
l
De todos estos items, sólo la palabra clave class y el nombre de la clase son necesarios. Los
otros son opcionales. Si no se realiza ninguna declaración explícita para los items opcionales, el
compilador Java asume ciertos valores por defecto (una subclase de Object no final, no pública,
no obstracta y que no implementa interfaces).
El Cuerpo de la Clase
Anteriormente se vió una descripción general de la implementación de una clase:
DeclaraciondeClase {
CuerpodeClase
}
La página anterior describe todos los componentes de la declaración de una clase.
Esta página describe la estructura general y la organización del cuerpo de la clase.
El cuerpo de la clase compone la implementación de la propia clase y contiene dos
secciones diferentes: la declaración de varibles y la de métodos. Una variable
miembro de la clase representa un estado de la clase y sus métodos implemetan el
comportamiendo de la clase. Dentro del cuerpo de la clase se definen todas las
variables miembro y los métodos soportados por la clase.
Típicamente, primero se declaran las variables miembro de la clase y luego se
porporciona las declaraciones e implementanciones de los métodos, aunque este
orden no es necesario.
DeclaracióndeClase {
DeclaracionesdeVariablesMiembros
DeclaracionesdeMétodos
}
Aquí tienes una pequeña clase que declara tres variables miembro y un método:
class Ticket {
Float precio;
String destino;
Date fechaSalida;
void firma(Float forPrecio, String forDestino, Date forFecha) {
precio = forPrecio;
destino = forDestino;
fechaSalida = forFecha;
}
}
Para más información sobre cómo declarar variables miembro, puedes ver Declarar
Variables Miembro. Y para obtener más información sobre cómo implementar
métodos, puedes ver Implementar Métodos.
Además de las variables miembro y los métodos que se declaran explícitamente
dentro del cuerpo de la clase, una clase puede heredar algo de su superclase. Por
ejemplo, todas las clases del entorno Java son una descendencia (directa o
indirecta) de la clase Object. La clase Object define el estado básico y el
comportamieto que todos los objetos deben tener como habilidad para comparar
unos objetos con otros, para convertir una cadena, para esperar una condición
variable, para notificar a otros objetos que una condición variable ha cambiado,
etc... Así, como descendentes de esta clase, todos los objetos del entorno Java
heredan sus comportamientos de la clase Object.
Leer más...
de las que crear esos objetos.
Una clase es un proyecto o prototipo que se puede utilizar para crear muchos objetos. La implementación
de una clase comprende dos componentes: la declaración y el cuerpo de la clase:
DeclaraciónDeLaClase {
CuerpoDeLaClase
}
La Declaración de la Clase
Como mínimo, la declaración de una clase debe contener la palabra clave class y el nombre de
la clase que está definiendo. Así la declaración más sencilla de una clase se parecería a esto:
class NombredeClase {
. . .
}
Por ejemplo, esta clase declara una nueva clase llamada NumeroImaginario:
class NumeroImaginario {
. . .
}
Los nombres de las clases deben ser un identificador legal de Java y, por convención, deben
empezar por una letra mayúscula. Muchas veces, todo lo que se necesitará será una
declaración mínima. Sin embargo, la declaración de una clase puede decir más cosas sobre la
clase. Más especificamente, dentro de la declaración de la clase se puede:
l declarar cual es la superclase de la clase.
l listar los interfaces implementados por la clase
l declarar si la clase es pública, abstracta o final
Declarar la Superclase de la Clase
En Java, todas las clases tienen una superclase. Si no se especifica una superclase para una
clase, se asume que es la clase Object (declarada en java.lang). Entonces la superclase de
NumeroImaginario es Object porque la declaración no explicitó ninguna otra clase. Para
obtener más información sobre la clase Object, puede ver La clase Object.
Para especificar explícitamente la superclase de una clase, se debe poner la palabra clave
extends más el nombre de la superclase entre el nombre de la clase que se ha creado y el
corchete abierto que abre el cuerpo de la clase, así:
class NombredeClase extends NombredeSuperClase {
. . .
}
Por ejemplo, supon que quieres que la superclase de NumeroImaginario sea la clase Number
en vez de la clase Object. Se podróa escribir esto:
class NumeroImaginario extends Number {
. . .
}
Esto declara explícitamente que la clase Number es la superclase de NumeroImaginario. (La
clase Number es parte del paquete java.lang y es la base para los enteros, los números en
coma flotante y otros números).
Declarar que Number es la superclase de NumeroImaginario declara implícitamente que
NumeroImaginario es una subclase de Number. Una subclase hereda las variables y los
métodos de su superclase.
Crear una subclase puede ser tan sencillo como incluir la clausula extends en su declaración
de clase. Sin embargo, se tendrán que hacer otras provisiones en su código cuando se crea una
subclase, como sobreescribir métodos. Para obtener más información sobre la creacción de
subclases, puede ver Subclases, Superclases, y Herencia.
Listar los Interfaces Implementados por la Clase
Cuando se declara una clase, se puede especificar que interface, si lo hay, está implementado
por la clase. Pero, ¿Qué es un interface? Un interface declara un conjunto de métodos y
constantes sin especificar su implementación para ningún método. Cuando una clase exige la
implementación de un interface, debe proporcionar la implementación para todos los métodos
declarados en el interface.
Para declarar que una clase implementa uno o más interfaces, se debe utilizar la palabra clave
implements seguida por una lista de los interfaces implementados por la clase delimitada por
comas. Por ejemplo, imagina un interface llamado Aritmetico que define los métodos llamados
suma(), resta(), etc... La clase NumeroImaginario puede declarar que implementa el
interface Aritmetico de esta forma:
class NumeroImaginario extends Number implements Aritmetico {
. . .
}
se debe garantizar que propociona la implementación para los métodos suma(), resta() y
demás métodos declarados en el interface Aritmetico. Si en NumeroImaginario falta alguna
implementación de los métodos definidos en Aritmetico, el compilador mostrará un mensaje de
error y no compilará el programa:
nothing.java:5: class NumeroImaginario must be declared abstract. It does not define
java.lang.Number add(java.lang.Number, java.lang.Number) from interface Aritmetico.
class NumeroImaginario extends Number implements Aritmetico {
^
Por convención, la clausula implements sigue a la clausula extends si ésta existe.
Observa que las firmas de los métodos declarados en el interface Aritmetico deben
corresponder con las firmas de los métodos implementados en la clase NumeroImaginario.
Tienes más información sobre cómo crear y utilizar interfaces en Crear y Utilizar Interfaces.
Clases Public, Abstract, y Final
Se puede utilizar uno de estos tres modificadores en una declaración de clase para declarar que
esa clase es pública, abstracta o final. Los modificadores van delante de la palabra clave class
y son opcionales.
El modificador public declara que la clase puede ser utilizada por objetos que estén fuera del
paquete actual. Por defecto, una clase sólo puede ser utiliza por otras clases del mismo
paquete en el que están declaradas.
public class NumeroImaginario extends Number implements Aritmetico {
. . .
}
Por convención, cuando se utiliza la palabra public en una declaración de clase debemos
asegurarnos de que es el primer item de la declaración.
El modificador abstract declara que la clase es una clase abstracta. Una clase abstracta podría
contener métodos abstractos (métodos sin implementación). Una clase abstracta está diseñada
para ser una superclase y no puede ejemplarizarse. Para una discusión sobre las clases
abstractas y cómo escribirlas puedes ver Escribir Clases y Métodos Abstractos.
Utilizando el modificador final se puede declarar que una clase es final, que no puede tener
subclases. Existen (al menos) dos razones por las que se podría querer hacer esto: razones de
seguridad y razones de diseño. Para un mejor explicaión sobre las clases finales puedes ver
Escribir Clases y Métodos Finales.
Observa que no tiene sentido para una clase ser abstracta y final. En otras palabras, una clase
que contenga métodos no implementados no puede ser final. Intentar declarar una clase como
final y abstracta resultará en un error en tiempo de compilación.
Sumario de la Daclaración de una Clase
En suma, una declaración de clase se parecería a esto:
[ modificadores ] class NombredeClase [ extends NombredeSuperclase ]
[ implements NombredeInterface ] {
. . .
}
Los puntos entre [ y ] son opcionales. Una declaración de clase define los siguientes aspectos
de una clase:
l modificadores declaran si la clase es abstracta, pública o final.
l NombredeClase selecciona el nombre de la clase que está declarando
l NombredeSuperClase es el nombre de la superclase de NombredeClase
NombredeInterface es una lista delimitada por comas de los interfaces implementados
por NombredeClase
l
De todos estos items, sólo la palabra clave class y el nombre de la clase son necesarios. Los
otros son opcionales. Si no se realiza ninguna declaración explícita para los items opcionales, el
compilador Java asume ciertos valores por defecto (una subclase de Object no final, no pública,
no obstracta y que no implementa interfaces).
El Cuerpo de la Clase
Anteriormente se vió una descripción general de la implementación de una clase:
DeclaraciondeClase {
CuerpodeClase
}
La página anterior describe todos los componentes de la declaración de una clase.
Esta página describe la estructura general y la organización del cuerpo de la clase.
El cuerpo de la clase compone la implementación de la propia clase y contiene dos
secciones diferentes: la declaración de varibles y la de métodos. Una variable
miembro de la clase representa un estado de la clase y sus métodos implemetan el
comportamiendo de la clase. Dentro del cuerpo de la clase se definen todas las
variables miembro y los métodos soportados por la clase.
Típicamente, primero se declaran las variables miembro de la clase y luego se
porporciona las declaraciones e implementanciones de los métodos, aunque este
orden no es necesario.
DeclaracióndeClase {
DeclaracionesdeVariablesMiembros
DeclaracionesdeMétodos
}
Aquí tienes una pequeña clase que declara tres variables miembro y un método:
class Ticket {
Float precio;
String destino;
Date fechaSalida;
void firma(Float forPrecio, String forDestino, Date forFecha) {
precio = forPrecio;
destino = forDestino;
fechaSalida = forFecha;
}
}
Para más información sobre cómo declarar variables miembro, puedes ver Declarar
Variables Miembro. Y para obtener más información sobre cómo implementar
métodos, puedes ver Implementar Métodos.
Además de las variables miembro y los métodos que se declaran explícitamente
dentro del cuerpo de la clase, una clase puede heredar algo de su superclase. Por
ejemplo, todas las clases del entorno Java son una descendencia (directa o
indirecta) de la clase Object. La clase Object define el estado básico y el
comportamieto que todos los objetos deben tener como habilidad para comparar
unos objetos con otros, para convertir una cadena, para esperar una condición
variable, para notificar a otros objetos que una condición variable ha cambiado,
etc... Así, como descendentes de esta clase, todos los objetos del entorno Java
heredan sus comportamientos de la clase Object.
Leer más...
Etiquetas:
basicos de java,
clases,
declarar clases
Crear Objetos
En Java, se crea un objeto mediante la creacción de un objeto de una clase o, en
otras palabras, ejemplarizando una clase. Aprenderás cómo crear una clase más
adelante en Crear Clases. Hasta entonces, los ejemplos contenidos aquí crean
objetos a apartir de clases que ya existen en el entorno Java.
Frecuentemente, se verá la creacción de un objeto Java con un sentencia como
esta:
Date hoy = new Date();
Esta sentencia crea un objeto Date (Date es una clase del paquete java,util). Esta
sentencia realmente realiza tres acciones: declaración, ejemplarización e
inicialización. Date hoy es una declaración de variable que sólo le dice al
compilador que el nombre hoy se va a utilizar para referirse a un objeto cuyo tipo
es Date, el operador new ejemplariza la clase Date (creando un nuevo objeto
Date), y Date() inicializa el objeto.
Declarar un Objeto
Ya que la declaración de un objeto es una parte innecesaria de la
creacción de un objeto, las declaraciones aparecen frecuentemente en la
misma línea que la creacción del objeto. Como cualquier otra declaración
de variable, las declaraciones de objetos pueden aparecer solitarias como
esta:
Date hoy;
De la misma forma, declarar una variable para contener un objeto es
exactamente igual que declarar una variable que va a contener un tipo
primitivo:
tipo nombre
donde tipo es el tipo de dato del objeto y nombre es el nombre que va a
utilizar el objeto. En Java, las clases e interfaces son como tipos de
datos. Entonces tipo puede ser el nombre de una clase o de un interface.
Las declaraciones notifican al compilador que se va a utilizar nombre
para referirse a una variable cuyo tipo es tipo. Las declaraciones no
crean nuevos objetos. Date hoy no crea un objeto Date, sólo crea un
nombre de variable para contener un objeto Date. Para ejemplarizar la
clase Date, o cualquier otra clase, se utiliza el operador new.
Ejemplarizar una Clase
El operador new ejemplariza una clase mediante la asignación de
memoria para el objeto nuevo de ese tipo. new necesita un sólo
argumento: una llamada al método constructor. Los métodos
constructores son métodos especiales proporcionados por cada clase
Java que son reponsables de la inicialización de los nuevos objetos de
ese tipo. El operador new crea el objeto, el constructor lo inicializa.
Aquí tienes un ejemplo del uso del operador new para crear un objeto
Rectangle (Rectangle es una clase del paquete java.awt):
new Rectangle(0, 0, 100, 200);
En el ejemplo, Rectangle(0, 0, 100, 200) es una llamada al
constructor de la clase Rectangle.
El operador new devuelve una referencia al objeto recien creado. Esta
referencia puede ser asignada a una variable del tipo apropiado.
Rectangle rect = new Rectangle(0, 0, 100, 200);
(Recuerda que una clase escencialmente define un tipo de dato de
referencia. Por eso, Rectangle puede utilizarse como un tipo de dato en
los programas Java. El valor de cualquier variable cuyo tipo sea un tipo
de referencia, es una referencia (un puntero) al valor real o conjunto de
valores representado por la variable.
Inicializar un Objeto
Como mencioné anteriormente, las clases porporcionan métodos
constructores para incializar los nuevos objetos de ese tipo. Una clase
podría proporcionar múltiples constructores para realizar diferentes tipos
de inicialización en los nuevos objetos. Cuando veas la implementación
de una clase, reconocerás los constructores porque tienen el mismo
nombre que la clase y no tienen tipo de retorno. Recuerda la creacción
del objeto Date en el sección inicial. El constructor utilizado no tenía
ningún argumento:
Date()
Un constructor que no tiene ningún argumento, como el mostrado arriba,
es conocido como constructor por defecto. Al igual que Date, la mayoría
de las clases tienen al menos un constructor, el constructor por defecto.
Si una clase tiene varios constructores, todos ellos tienen el mismo
nombre pero se deben diferenciar en el número o el tipo de sus
argmentos. Cada constructor inicializa el nuevo objeto de una forma
diferente. Junto al constructor por defecto, la clase Date proporciona otro
constructor que inicializa el nuevo objeto con un nuevo año, mes y dia:
Date cumpleaños = new Date(1963, 8, 30);
El compilador puede diferenciar los constructores a través del tipo y del
número de sus argumentos.
Utilizar Objetos
Una vez que se ha creado un objeto, probablemente querrás hacer algo con él.
Supón, por ejemplo, que después de crear un nuevo rectángulo, quieres moverlo a
una posición diferente (es decir, el rectángulo es un objeto en un programa de
dibujo y el usuario quiere moverlo a otra posición de la página).
La clase Rectangle proporciona dos formas equivalentes de mover el rectángulo:
1. Manipular directamente las variables x e y del objeto.
2. Llamar el método move().
La opción 2 se considera "más orientada a objetos" y más segura porque se
manipulan las variables del objeto indirectamente a través de una capa protectora
de métodos, en vez de manejarlas directamente. Manipular directamente las
variables de un objeto se considera propenso a errores; se podría colocar el objeto
en un estado de inconsistencia. Sin embargo, una clase no podría (y no debería)
hacer que sus variables estuvieran disponibles para la manipulación directa por
otros objetos, si fuera posible que esas manipulaciones situaran el objeto en un
estado de inconsistencia. Java proporciona un mecanismo mediante el que las
clases puede restringir o permitir el acceso a sus variables y métodos a otros
objetos de otros tipos.
Esta sección explica la llamada a métodos y la manipulación de variables que se
han hecho accesibles a otras clases. Para aprender más sobre el control de acceso
a miembros puedes ir Controlar el Acceso a Miembros de una Clase.
Las variables x e y de Rectangle son accesibles desde otras clases. Por eso
podemos asumir que la manipulación directa de estas variables es segura.
Referenciar Variables de un Objeto
Primero, enfoquemos cómo inspeccionar y modificar la posición del
rectángulo mediante la manipulación directa de las variables x e y. La
siguiente sección mostrará como mover el rectángulo llamando al
método move().
Para acceder a las variables de un objeto, sólo se tiene que añadir el
nombre de la variable al del objeto referenciado introduciendo un punto
en el medio ('.').
objetoReferenciado.variable
Supón que tienes un rectángulo llamado rect en tu programa. puedes
acceder a las variables x e y con rect.x y rect.y, respectivamente.
Ahora que ya tienes un nombre para las variables de rect, puedes
utilizar ese nombre en sentencias y expresiones Java como si fueran
nombres de variables "normales". Así, para mover el rectángulo a una
nueva posición podrías escribir:
rect.x = 15; // cambia la posición x
rect.y = 37; // cambia la posición y
La clase Rectangle tiene otras dos variables--widthy height--que son
accesibles para objetos fuera de Rectangle. Se puede utilizar la misma
notación con ellas: rect.width y rect.height. Entonces se puede
calcular el área del rectángulo utilizando esta sentencia:
area = rect.height * rect.width;
Cuando se accede a una variable a través de un objeto, se está
refiriendo a las variables de un objeto particular. Si cubo fuera también
un rectángulo con una altura y anchura diferentes de rect, esta
instrucción:
area = cubo.height * cubo.width;
calcula el área de un rectángulo llamado cubo y dará un resultado
diferente que la instrucción anterior (que calculaba el área de un
rectángulo llamado rect).
Observa que la primera parte del nombre de una variable de un objeto
(el objetoReferenciado en objetoReferenciado.variable) debe ser
una referencia a un objeto. Como se puede utilizar un nombre de
variable aquí, también se puede utilizar en cualquier expresión que
devuelva una referencia a un objeto. Recuerda que el operador new
devuelve una referencia a un objeto. Por eso, se puede utilizar el valor
devuelto por new para acceder a las variables del nuevo objeto:
height = new Rectangle().height;
Llamar a Métodos de un Objeto
Llamar a un método de un objeto es similar a obtener una variable del
objeto. Para llamar a un método del objeto, simplemente se añade al
nombre del objeto referenciado el nombre del método, separados por un
punto ('.'), y se proporcionan los argumentos del método entre
paréntesis. Si el método no necesita argumentos, se utilizan los
paréntesis vacios.
objetoReferenciado.nombreMétodo(listaArgumentos);
o
objetoReferenciado.nombreMétodo();
Veamos que significa esto en términos de movimiento del rectángulo.
Para mover rect a una nueva posición utilizando el método move()
escribe esto:
rect.move(15, 37);
Esta sentencia Java llama al método move() de rect con dos
parámetros enteros, 15 y 37. Esta sentencia tiene el efecto de mover el
objeto rect igual que se hizo en las sentencias anteriores en las que se
moficaban directamente los valores x e y del objeto:
rect.x = 15;
rect.y = 37;
Si se quiere mover un rectángulo diferente, uno llamado cubo, la nueva
posición se podría escribir:
cubo.move(244, 47);
Como se ha visto en estos ejemplos, las llamadas a métodos se hacen
directamente a un objeto específico; el objeto especificado en la llamada
al método es el que responde a la instrucción.
Las llamadas a métodos también se conocen como mensajes. Como en la
vida real, los mensajes se deben dirigir a un receptor particular. Se
pueden obtener distintos resultados dependiendo del receptor de su
mensaje. En el ejemplo anterior, se ha enviado el mensaje move() al
objeto llamado rect para que éste mueva su posición. Cuando se envía
el mensaje move() al objeto llamado cubo, el que se mueve es cubo.
Son resultados muy distintos.
Una llamada a un método es una expresión (puedes ver Expresiones
para más información) y evalúa a algún valor. El valor de una llamada a
un método es su valor de retorno, si tiene alguno. Normalmente se
asignará el valor de retorno de un método a una variable o se utilizará la
llamada al método dentro del ámbito de otra expresión o sentencia.
El método move() no devuelve ningún valor (está declarado como
void). Sin embargo, el método inside() de Rectangle si lo hace. Este
método toma dos coordendas x e y, y devuelte true si este punto está
dentro del rectángulo. Se puede utilizar el método inside() para hacer
algo especial en algún punto, como decir la posición del ratón cuando
está dentro del rectangulo:
if (rect.inside(mouse.x, mouse.y)) {
. . .
// ratón dentro del rectángulo
. . .
} else {
. . .
// ratón fuera del rectángulo
. . .
}
Recuerda que una llamada a un método es un mensaje al objeto
nombrado. En este caso, el objeto nombrado es rect. Entonces:
rect.inside(mouse.x, mouse.y)
le pregunta a rect si la posición del cursor del ratón se encuentra entre
las coordenadas mouse.x y mouse.y. Se podría obtener una respuesta
diferente si envía el mismo mensaje a cubo.
Como se explicó anteriormente, el objetoReferenciado en la llamada al
método objetoReferenciado.método() debe ser una referencia a un
objeto. Como se puede utilizar un nombre de variable aquí, también se
puede utilizar en cualquier expresión que devuelva una referencia a un
objeto. Recuerda que el operador new devuelve una referencia a un
objeto. Por eso, se puede utilizar el valor devuelto por new para acceder
a las variables del nuevo objeto:
new Rectangle(0, 0, 100, 50).equals(anotherRect)
La expresión new Rectangle(0, 0, 100, 50) evalúa a una referencia a
un objeto que se refiere a un objeto Rectangle. Entonces, como verás, se
puede utilizar la notació de punto ('.') para llamar al método equals()
del nuevo objeto Rectangle para determinar si el rectangúlo nuevo es
igual al especificado en la lista de argumentos de equals().
Leer más...
otras palabras, ejemplarizando una clase. Aprenderás cómo crear una clase más
adelante en Crear Clases. Hasta entonces, los ejemplos contenidos aquí crean
objetos a apartir de clases que ya existen en el entorno Java.
Frecuentemente, se verá la creacción de un objeto Java con un sentencia como
esta:
Date hoy = new Date();
Esta sentencia crea un objeto Date (Date es una clase del paquete java,util). Esta
sentencia realmente realiza tres acciones: declaración, ejemplarización e
inicialización. Date hoy es una declaración de variable que sólo le dice al
compilador que el nombre hoy se va a utilizar para referirse a un objeto cuyo tipo
es Date, el operador new ejemplariza la clase Date (creando un nuevo objeto
Date), y Date() inicializa el objeto.
Declarar un Objeto
Ya que la declaración de un objeto es una parte innecesaria de la
creacción de un objeto, las declaraciones aparecen frecuentemente en la
misma línea que la creacción del objeto. Como cualquier otra declaración
de variable, las declaraciones de objetos pueden aparecer solitarias como
esta:
Date hoy;
De la misma forma, declarar una variable para contener un objeto es
exactamente igual que declarar una variable que va a contener un tipo
primitivo:
tipo nombre
donde tipo es el tipo de dato del objeto y nombre es el nombre que va a
utilizar el objeto. En Java, las clases e interfaces son como tipos de
datos. Entonces tipo puede ser el nombre de una clase o de un interface.
Las declaraciones notifican al compilador que se va a utilizar nombre
para referirse a una variable cuyo tipo es tipo. Las declaraciones no
crean nuevos objetos. Date hoy no crea un objeto Date, sólo crea un
nombre de variable para contener un objeto Date. Para ejemplarizar la
clase Date, o cualquier otra clase, se utiliza el operador new.
Ejemplarizar una Clase
El operador new ejemplariza una clase mediante la asignación de
memoria para el objeto nuevo de ese tipo. new necesita un sólo
argumento: una llamada al método constructor. Los métodos
constructores son métodos especiales proporcionados por cada clase
Java que son reponsables de la inicialización de los nuevos objetos de
ese tipo. El operador new crea el objeto, el constructor lo inicializa.
Aquí tienes un ejemplo del uso del operador new para crear un objeto
Rectangle (Rectangle es una clase del paquete java.awt):
new Rectangle(0, 0, 100, 200);
En el ejemplo, Rectangle(0, 0, 100, 200) es una llamada al
constructor de la clase Rectangle.
El operador new devuelve una referencia al objeto recien creado. Esta
referencia puede ser asignada a una variable del tipo apropiado.
Rectangle rect = new Rectangle(0, 0, 100, 200);
(Recuerda que una clase escencialmente define un tipo de dato de
referencia. Por eso, Rectangle puede utilizarse como un tipo de dato en
los programas Java. El valor de cualquier variable cuyo tipo sea un tipo
de referencia, es una referencia (un puntero) al valor real o conjunto de
valores representado por la variable.
Inicializar un Objeto
Como mencioné anteriormente, las clases porporcionan métodos
constructores para incializar los nuevos objetos de ese tipo. Una clase
podría proporcionar múltiples constructores para realizar diferentes tipos
de inicialización en los nuevos objetos. Cuando veas la implementación
de una clase, reconocerás los constructores porque tienen el mismo
nombre que la clase y no tienen tipo de retorno. Recuerda la creacción
del objeto Date en el sección inicial. El constructor utilizado no tenía
ningún argumento:
Date()
Un constructor que no tiene ningún argumento, como el mostrado arriba,
es conocido como constructor por defecto. Al igual que Date, la mayoría
de las clases tienen al menos un constructor, el constructor por defecto.
Si una clase tiene varios constructores, todos ellos tienen el mismo
nombre pero se deben diferenciar en el número o el tipo de sus
argmentos. Cada constructor inicializa el nuevo objeto de una forma
diferente. Junto al constructor por defecto, la clase Date proporciona otro
constructor que inicializa el nuevo objeto con un nuevo año, mes y dia:
Date cumpleaños = new Date(1963, 8, 30);
El compilador puede diferenciar los constructores a través del tipo y del
número de sus argumentos.
Utilizar Objetos
Una vez que se ha creado un objeto, probablemente querrás hacer algo con él.
Supón, por ejemplo, que después de crear un nuevo rectángulo, quieres moverlo a
una posición diferente (es decir, el rectángulo es un objeto en un programa de
dibujo y el usuario quiere moverlo a otra posición de la página).
La clase Rectangle proporciona dos formas equivalentes de mover el rectángulo:
1. Manipular directamente las variables x e y del objeto.
2. Llamar el método move().
La opción 2 se considera "más orientada a objetos" y más segura porque se
manipulan las variables del objeto indirectamente a través de una capa protectora
de métodos, en vez de manejarlas directamente. Manipular directamente las
variables de un objeto se considera propenso a errores; se podría colocar el objeto
en un estado de inconsistencia. Sin embargo, una clase no podría (y no debería)
hacer que sus variables estuvieran disponibles para la manipulación directa por
otros objetos, si fuera posible que esas manipulaciones situaran el objeto en un
estado de inconsistencia. Java proporciona un mecanismo mediante el que las
clases puede restringir o permitir el acceso a sus variables y métodos a otros
objetos de otros tipos.
Esta sección explica la llamada a métodos y la manipulación de variables que se
han hecho accesibles a otras clases. Para aprender más sobre el control de acceso
a miembros puedes ir Controlar el Acceso a Miembros de una Clase.
Las variables x e y de Rectangle son accesibles desde otras clases. Por eso
podemos asumir que la manipulación directa de estas variables es segura.
Referenciar Variables de un Objeto
Primero, enfoquemos cómo inspeccionar y modificar la posición del
rectángulo mediante la manipulación directa de las variables x e y. La
siguiente sección mostrará como mover el rectángulo llamando al
método move().
Para acceder a las variables de un objeto, sólo se tiene que añadir el
nombre de la variable al del objeto referenciado introduciendo un punto
en el medio ('.').
objetoReferenciado.variable
Supón que tienes un rectángulo llamado rect en tu programa. puedes
acceder a las variables x e y con rect.x y rect.y, respectivamente.
Ahora que ya tienes un nombre para las variables de rect, puedes
utilizar ese nombre en sentencias y expresiones Java como si fueran
nombres de variables "normales". Así, para mover el rectángulo a una
nueva posición podrías escribir:
rect.x = 15; // cambia la posición x
rect.y = 37; // cambia la posición y
La clase Rectangle tiene otras dos variables--widthy height--que son
accesibles para objetos fuera de Rectangle. Se puede utilizar la misma
notación con ellas: rect.width y rect.height. Entonces se puede
calcular el área del rectángulo utilizando esta sentencia:
area = rect.height * rect.width;
Cuando se accede a una variable a través de un objeto, se está
refiriendo a las variables de un objeto particular. Si cubo fuera también
un rectángulo con una altura y anchura diferentes de rect, esta
instrucción:
area = cubo.height * cubo.width;
calcula el área de un rectángulo llamado cubo y dará un resultado
diferente que la instrucción anterior (que calculaba el área de un
rectángulo llamado rect).
Observa que la primera parte del nombre de una variable de un objeto
(el objetoReferenciado en objetoReferenciado.variable) debe ser
una referencia a un objeto. Como se puede utilizar un nombre de
variable aquí, también se puede utilizar en cualquier expresión que
devuelva una referencia a un objeto. Recuerda que el operador new
devuelve una referencia a un objeto. Por eso, se puede utilizar el valor
devuelto por new para acceder a las variables del nuevo objeto:
height = new Rectangle().height;
Llamar a Métodos de un Objeto
Llamar a un método de un objeto es similar a obtener una variable del
objeto. Para llamar a un método del objeto, simplemente se añade al
nombre del objeto referenciado el nombre del método, separados por un
punto ('.'), y se proporcionan los argumentos del método entre
paréntesis. Si el método no necesita argumentos, se utilizan los
paréntesis vacios.
objetoReferenciado.nombreMétodo(listaArgumentos);
o
objetoReferenciado.nombreMétodo();
Veamos que significa esto en términos de movimiento del rectángulo.
Para mover rect a una nueva posición utilizando el método move()
escribe esto:
rect.move(15, 37);
Esta sentencia Java llama al método move() de rect con dos
parámetros enteros, 15 y 37. Esta sentencia tiene el efecto de mover el
objeto rect igual que se hizo en las sentencias anteriores en las que se
moficaban directamente los valores x e y del objeto:
rect.x = 15;
rect.y = 37;
Si se quiere mover un rectángulo diferente, uno llamado cubo, la nueva
posición se podría escribir:
cubo.move(244, 47);
Como se ha visto en estos ejemplos, las llamadas a métodos se hacen
directamente a un objeto específico; el objeto especificado en la llamada
al método es el que responde a la instrucción.
Las llamadas a métodos también se conocen como mensajes. Como en la
vida real, los mensajes se deben dirigir a un receptor particular. Se
pueden obtener distintos resultados dependiendo del receptor de su
mensaje. En el ejemplo anterior, se ha enviado el mensaje move() al
objeto llamado rect para que éste mueva su posición. Cuando se envía
el mensaje move() al objeto llamado cubo, el que se mueve es cubo.
Son resultados muy distintos.
Una llamada a un método es una expresión (puedes ver Expresiones
para más información) y evalúa a algún valor. El valor de una llamada a
un método es su valor de retorno, si tiene alguno. Normalmente se
asignará el valor de retorno de un método a una variable o se utilizará la
llamada al método dentro del ámbito de otra expresión o sentencia.
El método move() no devuelve ningún valor (está declarado como
void). Sin embargo, el método inside() de Rectangle si lo hace. Este
método toma dos coordendas x e y, y devuelte true si este punto está
dentro del rectángulo. Se puede utilizar el método inside() para hacer
algo especial en algún punto, como decir la posición del ratón cuando
está dentro del rectangulo:
if (rect.inside(mouse.x, mouse.y)) {
. . .
// ratón dentro del rectángulo
. . .
} else {
. . .
// ratón fuera del rectángulo
. . .
}
Recuerda que una llamada a un método es un mensaje al objeto
nombrado. En este caso, el objeto nombrado es rect. Entonces:
rect.inside(mouse.x, mouse.y)
le pregunta a rect si la posición del cursor del ratón se encuentra entre
las coordenadas mouse.x y mouse.y. Se podría obtener una respuesta
diferente si envía el mismo mensaje a cubo.
Como se explicó anteriormente, el objetoReferenciado en la llamada al
método objetoReferenciado.método() debe ser una referencia a un
objeto. Como se puede utilizar un nombre de variable aquí, también se
puede utilizar en cualquier expresión que devuelva una referencia a un
objeto. Recuerda que el operador new devuelve una referencia a un
objeto. Por eso, se puede utilizar el valor devuelto por new para acceder
a las variables del nuevo objeto:
new Rectangle(0, 0, 100, 50).equals(anotherRect)
La expresión new Rectangle(0, 0, 100, 50) evalúa a una referencia a
un objeto que se refiere a un objeto Rectangle. Entonces, como verás, se
puede utilizar la notació de punto ('.') para llamar al método equals()
del nuevo objeto Rectangle para determinar si el rectangúlo nuevo es
igual al especificado en la lista de argumentos de equals().
Leer más...
Etiquetas:
basicos de java,
clases,
crear objetos,
objetos
Suscribirse a:
Comentarios (Atom)

