NOMBRE: FCO. JAVIER VAZQUEZ PANTALEON. CARRERA: INGENIERIA EN SISTEMAS COMPUTACIONALES. SCHOOL: INSTITUTO TECNOLOGICO DE LAZARO CARDENAS MICHOACAN.

->MEXICO<- ->ARGENTINA<- ->ESPAÑA<-

Reproductor


Ringtones
Reproductor Mi musica ... en ...

Mostrando entradas con la etiqueta conseptos basicos de java. Mostrar todas las entradas
Mostrando entradas con la etiqueta conseptos basicos de java. Mostrar todas las entradas

martes, 15 de septiembre de 2009

Controlar el Acceso a los Miembros de la Clase

Uno de los beneficos de las clases es que pueden proteger sus variables y métodos miembros
frente al acceso de otros objetos. ¿Por qué es esto importante? Bien, consideremos esto. Se ha
escrito una clase que representa una petición a una base de datos que contiene toda clase de
información secreta, es decir, registros de empleados o proyectos secretos de la compañia.
Ciertas informaciones y peticiones contenidas en la clase, las soportadas por los métodos y
variables accesibles públicamente en su objeto son correctas para el consumo de cualquier otro
objeto del sistema. Otras peticiones contenidas en la clase son sólo para el uso personal de la
clase. Estas otras soportadas por la operación de la clase no deberían ser utilizadas por objetos de otros tipos. Se querría proteger esas variables y métodos personales a nivel del lenguaje y prohibir el acceso desde objetos de otros tipos.
En Java se puede utilizar los especificadores de acceso para proteger tanto las variables como los métodos de la clase cuando se declaran. El lenguaje Java soporta cuatro niveles de acceso para las variables y métodos miembros: private, protected, public, y, todavía no especificado, acceso de paquete.

La siguiente tabla le muestra los niveles de acceso pemitidos por cada especificador:
Especificador clase subclase paquete mundo
private X
protected X X* X
public X X X X
package X X
La primera columna indica si la propia clase tiene acceso al miembro definido por el especificador
de acceso. La segunda columna indica si las subclases de la clase (sin importar dentro de que
paquete se encuentren estas) tienen acceso a los miembros. La tercera columna indica si las
clases del mismo paquete que la clase (sin importar su parentesco) tienen acceso a los miembros.
La cuarta columna indica si todas las clases tienen acceso a los miembros.
Observa que la intersección entre protected y subclase tiene un '*' - este caso de acceso particular
tiene una explicación en más detalle más adelante.
Echemos un vistazo a cada uno de los niveles de acceso más detalladamente:
Private
El nivel de acceso más restringido es private. Un miembro privado es accesible sólo para
la clase en la que está definido. Se utiliza este acceso para declarar miembros que sólo
deben ser utilizados por la clase. Esto incluye las variables que contienen informaión
que si se accede a ella desde el exterior podría colocar al objeto en un estado de
inconsistencia, o los métodos que llamados desde el exterior pueden ponen en peligro el
estado del objeto o del programa donde se está ejecutando. Los miembros privados son
como secretos, nunca deben contarsele a nadie.
Para declarar un miembro privado se utiliza la palabra clave private en su declaración.
La clase siguiente contiene una variable miembro y un método privados:
class Alpha {
private int soyPrivado;
private void metodoPrivado() {
System.out.println("metodoPrivado");
}
}
Los objetos del tipo Alpha pueden inspeccionar y modificar la variable soyPrivado y
pueden invocar el método metodoPrivado(), pero los objetos de otros tipos no pueden
acceder. Por ejemplo, la clase Beta definida aquí:
class Beta {
void metodoAccesor() {
Alpha a = new Alpha();
a.soyPrivado = 10; // ilegal
a.metodoPrivado(); // ilegal
}
}
no puede acceder a la variable soyPrivado ni al método metodoPrivado() de un
objeto del tipo Alpha porque Beta no es del tipo Alpha.
Si una clase está intentando acceder a una variable miembro a la que no tiene
acceso--el compilador mostrará un mensaje de error similar a este y no compilará su
programa:
Beta.java:9: Variable iamprivate in class Alpha not accessible from class Beta.
a.iamprivate = 10; // ilegal
^
1 error
Y si un programa intenta acceder a un método al que no tiene acceso, generará un error
de compilación parecido a este:
Beta.java:12: No method matching privateMethod() found in class Alpha.
a.privateMethod(); // ilegal
1 error
Protected
El siguiente especificador de nivel de acceso es 'protected' que permite a la propia clase,
las subclases (con la excepción a la que nos referimos anteriormente), y todas las clases
dentro del mismo paquete que accedan a los miembros. Este nivel de acceso se utiliza
cuando es apropiado para una subclase da la clase tener acceso a los miembros, pero
no las clases no relacionadas. Los miembros protegidos son como secretos familiares -
no importa que toda la familia lo sepa, incluso algunos amigos allegados pero no se
quiere que los extraños lo sepan.
Para declarar un miembro protegido, se utiliza la palabra clave protected. Primero
echemos un vistazo a cómo afecta este especificador de acceso a las clases del mismo
paquete.
Consideremos esta versión de la clase Alpha que ahora se declara para estar incluida en
el paquete Griego y que tiene una variable y un método que son miembros protegidos:
package Griego;
class Alpha {
protected int estoyProtegido;
protected void metodoProtegido() {
System.out.println("metodoProtegido");
}
}
Ahora, supongamos que la clase Gamma, también está declarada como miembro del
paquete Griego (y no es una subclase de Alpha). La Clase Gamma puede acceder
legalmente al miembro estoyProtegido del objeto Alpha y puede llamar legalmente a
su método metodoProtegido():
package Griego;
class Gamma {
void metodoAccesor() {
Alpha a = new Alpha();
a.estoyProtegido = 10; // legal
a.metodoProtegido(); // legal
}
}
Esto es muy sencillo. Ahora, investiguemos cómo afecta el especificador portected a una
subclase de Alpha.
Introduzcamos una nueva clase, Delta, que desciende de la clase Alpha pero reside en
un paquete diferente - Latin. La clase Delta puede acceder tanto a estoyProtegido
como a metodoProtegido(), pero solo en objetos del tipo Delta o sus subclases. La
clase Delta no puede acceder a estoyProtegido o metodoProtegido() en objetos del
tipo Alpha. metodoAccesor() en el siguiente ejemplo intenta acceder a la variable
miembro estoyProtegido de un objeto del tipo Alpha, que es ilegal, y en un objeto del
tipo Delta que es legal. Similarmente, metodoAccesor() intenta invocar a
metodoProtegido() en un objeto del tipo Alpha, que también es ilegal:
import Griego.*;
package Latin;
class Delta extends Alpha {
void metodoAccesor(Alpha a, Delta d) {
a.estoyProtegido = 10; // ilegal
d.estoyProtegido = 10; // legal
a.metodoProtegido(); // ilegal
d.metodoProtegido(); // legal
}
}
Si una clase es una subclase o se cuentra en el mismo paquete de la clase con el
miembro protegido, la clase tiene acceso al miembro protegido.
Public
El especificador de acceso más sencillo es 'public'. Todas las clases, en todos los
paquetes tienen acceso a los miembros públicos de la clase. Los miembros públicos se
declaran ólo si su acceso no produce resultados indeseados si un extraño los utiliza.
Aquí no hay secretos familiares; no importa que lo sepa todo el mundo.
Para declarar un miembro público se utiliza la palabra clave public. Por ejemplo,
package Griego;
class Alpha {
public int soyPublico;
public void metodoPublico() {
System.out.println("metodoPublico");
}
}
Reescribamos nuestra clase Beta una vez más y la ponemos en un paquete diferente
que la clase Alpha y nos aseguramos que no están relacionadas (no es una subclase) de
Alpha:
import Griego.*;
package Romano;
class Beta {
void metodoAccesor() {
Alpha a = new Alpha();
a.soyPublico = 10; // legal
a.metodoPublico(); // legal
}
}
Como se puede ver en el ejemplo anterior, Beta puede inspeccionar y modificar
legalmente la variable soyPublico en la clase Alpha y puede llamar legalmente al
método metodoPublico().
Acceso de Paquete
Y finalmente, el último nivel de acceso es el que se obtiene si no se especifica ningún
otro nivel de acceso a loss miembros. Este nivel de acceso permite que las clases del
mismo paquete que la clase tengan acceso a los miembros. Este nivel de acceso asume
que las clases del mismo paquete son amigas de confianza. Este nivel de confianza es
como la que extiende a sus mejores amigos y que incluso no la tiene con su familia.
Por ejemplo, esta versión de la clase Alpha declara una variable y un método con acceso
de paquete. Alpha reside en el paquete Griego:
package Griego;
class Alpha {
int estoyEmpaquetado;
void metodoEmpaquetado() {
System.out.println("metodoEmpaquetado");
}
}
La clase Alpha tiene acceso a estoyEmpaquetado y a metodoEmpaquetado().
Además, todas las clases declaradas dentro del mismo paquete como Alpha también
tienen acceso a estoyEmpaquetado y metodoEmpaquetado(). Supongamos que
tanto Alpha como Beta son declaradas como parte del paquete Griego:
package Griego;
class Beta {
void metodoAccesor() {
Alpha a = new Alpha();
a.estoyEmpaquetado = 10; // legal
a.metodoEmpaquetado(); // legal
}
}
Entonces Beta puede acceder legalmente a estoyEmpaquetado y
metodoEmpaquetado().
Ozito

Constructores
Todas las clases Java tienen métodos especiales llamados Constructores que se
utilizan para inicializar un objeto nuevo de ese tipo. Los contructores tienen el
mismo nombre que la clase --el nombre del constructor de la clase Rectangle es
Rectangle(), el nombre del constructor de la clase Thread es Thread(), etc...
Java soporta la sobrecarga de los nombres de métodos para que una clase puede
tener cualquier número de constructores, todos los cuales tienen el mismo nombre.
Al igual que otros métodos sobrecargados, los constructores se diferencian unos de
otros en el número y tipo de sus argumentos.
Consideremos la clase Rectangle del paquete java.awt que proporciona varios
constructores diferentes, todos llamados Rectangle(), pero cada uno con número
o tipo diferentes de argumentos a partir de los cuales se puede crear un nuevo
objeto Rectangle. Aquí tiene las firmas de los constructores de la clase
java.awt.Rectangle:
public Rectangle()
public Rectangle(int width, int height)
public Rectangle(int x, int y, int width, int height)
public Rectangle(Dimension size)
public Rectangle(Point location)
public Rectangle(Point location, Dimension size)
El primer constructor de Rectangle inicializa un nuevo Rectangle con algunos
valores por defecto razonables, el segundo constructor inicializa el nuevo Rectangle
con la altura y anchura especificadas, el tercer constructor inicializa el nuevo
Rectangle en la posición especificada y con la altura y anchura especificadas, etc...
Típicamente, un constructor utiliza sus argumentos para inicializar el estado del
nuevo objeto. Entonces, cuando se crea un objeto, se debe elegir el constructor
cuyos argumentos reflejen mejor cómo se quiere inicializar el objeto.
Basándose en el número y tipos de los argumentos que se pasan al constructor, el
compilador determina cual de ellos utilizar, Así el compilador sabe que cuando se
escribe:
new Rectangle(0, 0, 100, 200);
el compilador utilizará el constructor que requiere cuatro argumentos enteros, y
cuando se escribe:
new Rectangle(miObjetoPoint, miObjetoDimension);
utilizará el constructor que requiere como argumentos un objeto Point y un objeto
Dimension.
Cuando escribas tus propias clases, no tienes porque proporcionar constructores. El
constructor por defecto, el constructor que no necesita argumentos, lo proporciona
automáticamente el sistema para todas las clases. Sin embargo, frecuentemente
se querrá o necesitará proporcionar constructores para las clases.
Se puede declarar e implementar un constructor como se haría con cualquier otro
método en una clase. El nombre del constructor debe ser el mismo que el nombre
de la clase y, si se proporciona más de un constructor, los argumentos de cada uno
de los constructores deben diferenciarse en el número o tipo. No se tiene que
especificar el valor de retorno del constructor.
El constructor para esta subclase de Thread, un hilo que realiza animación,
selecciona algunos valores por defecto como la velocidad de cuadro, el número de
imágenes y carga las propias imágenes:
class AnimationThread extends Thread {
int framesPerSecond;
int numImages;
Image[] images;
AnimationThread(int fps, int num) {
int i;
super("AnimationThread");
this.framesPerSecond = fps;
this.numImages = num;
this.images = new Image[numImages];
for (i = 0; i <= numImages; i++) {
. . .
// Carga las imágenes
. . .
}
}
}
Observa cómo el cuerpo de un constructor es igual que el cuerpo de cualquier otro
método -- contiene declaraciones de variables locales, bucles, y otras sentencias.
Sin embargo, hay una línea en el constructor de AnimationThread que no se verá
en un método normal--la segunda línea:
super("AnimationThread");
Esta línea invoca al constructor proporcionado por la superclase de
AnimationThread--Thread. Este constructor particular de Thread acepta una cadena
que contiene el nombre del Thread. Frecuentemente un constructor se aprovechará
del código de inicialziación escrito para la superclase de la clase.
En realidad, algunas clases deben llamar al constructor de su superclase para que
el objeto trabaje de forma apropiada. Tipicamente, llamar al constructor de la
superclase es lo primero que se hace en el constructor de la subclase: un objeto
debe realizar primero la inicialización de nivel superior.
Cuando se declaren constructores para las clases, se pueden utilizar los
especificadores de acceso normales para especificar si otros objetos pueden crear
ejemplares de sus clase:
private
Niguna otra clase puede crear un objeto de su clase. La clase puede contener
métodos públicos y esos métodos pueden construir un objeto y devolverlo,
pero nada más.
protected
Sólo las subclases de la clase pueden crear ejemplares de ella.
public
Cualquiera pueda crear un ejemplar de la clase.
package-access
Nadie externo al paquete puede construir un ejemplar de su clase. Esto es
muy útil si se quiere que las clase que tenemos en un paquete puedan crear
ejemplares de la clase pero no se quiere que lo haga nadie más.
Leer más...

Implementación de Métodos

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...

variable y tipos de datos

Las variables son las partes importantes de un lenguaje de programación: ellas son
las entidades (valores, datos) que actúan y sobre las que se actúa.
Una declaración de variable siempre contiene dos componentes, el tipo de la
variable y su nombre:
tipoVariable nombre;

Tipos de Variables
Todas las variables en el lenguaje Java deben tener un tipo de dato. El
tipo de la variable determina los valores que la variable puede contener y
las operaciones que se pueden realizar con ella.
Existen dos categorias de datos principales en el lenguaje Java: los tipos
primitivos y los tipos referenciados.
Los tipos primitivos contienen un sólo valor e incluyen los tipos como los
enteros, coma flotante, los caracteres, etc... La tabla siguiente muestra
todos los tipos primitivos soportados por el lenguaje Java, su formato, su
tamaño y una breve descripción de cada uno:
Tipo Tamaño/Formato Descripción
(Números enteros)
byte 8-bit complemento a 2 Entero de un Byte
short 16-bit complemento a 2 Entero corto
int 32-bit complemento a 2 Entero
long 64-bit complemento a 2 Entero largo
(Números reales)
float 32-bit IEEE 754 Coma flotante de precisión simple
double 64-bit IEEE 754 Coma flotante de precisión doble
(otros tipos)
char 16-bit Caracter Un sólo carácter
boolean true o false Un valor booleano (verdadero o falso)
Los tipos referenciados se llaman así porque el valor de una variable de
referencia es una referencia (un puntero) hacia el valor real. En Java
tenemos los arrays, las clases y los interfaces como tipos de datos
referenciados.
Nombres de Variables
Un programa se refiere al valor de una variable por su nombre. Por
convención, en Java, los nombres de las variables empiezan con una
letra minúscula (los nombres de las clases empiezan con una letra
mayúscula).
Un nombre de variable Java:
debe ser un identificador legal de Java comprendido en una serie de
caracteres Unicode. Unicode es un sistema de codificación que
soporta texto escrito en distintos lenguajes humanos.Unicode
perminte la codificación de 34.168 caracteres. Esto le permite
utilizar en sus programas Java varios alfabetos como el Japonés, el
Griego, el Ruso o el Hebreo. Esto es importante para que los
programadores pueden escribir código en su lenguaje nativo.
1.
no puede ser el mismo que una palabra clave o el nombre de un
valor booleano (true or false)
2.
no deben tener el mismo nombre que otras variables cuyas
declaraciones aparezcan en el mismo ámbito.
3.
La regla número 3 implica que podría existir el mismo nombre en otra
variable que aparezca en un ámbito diferente.
Por convención, los nombres de variables empiezan por un letra
minúscula. Si una variable está compuesta de más de una palabra, como
'nombreDato' las palabras se ponen juntas y cada palabra después de la
primera empieza con una letra mayúscula.
Leer más...

Conceptos Básicos java

Se puede hablar de Programación Orientada a Objetos cuando se reúnen las características de: abstracción, encapsulación, herencia y polimorfismo; y los conceptos básicos que las forman: objetos, mensajes, clases, instancias y métodos.

Conceptos Básicos:

* Un objeto es una encapsulación abstracta de información, junto con los métodos o procedimientos para manipularla. Un objeto contiene operaciones que definen su comportamiento y variables que definen su estado entre las llamadas a las operaciones.
* Una clase equivale a la generalización o abstracción de un tipo específico de objetos.
* Un mensaje representa una acción a tomar por un determinado objeto.
* Una instancia es la concrección de una clase.
* Un método consiste en la implementación en una clase de un protocolo de respuesta a los mensajes dirigidos a los objetos de la misma. La respuesta a tales mensajes puede incluir el envío por el método de mensajes al propio objeto y aun a otros, también como el cambio del estado interno del objeto.

Características:

La abstracción: Consiste en la generalización conceptual de un determinado conjunto de objetos y de sus atributos y propiedades, dejando en un segundo término los detalles concretos de cada objeto. ¿Qué se consigue con la abstracción? Bueno, básicamente pasar del plano material (cosas que se tocan) al plano mental (cosas que se piensan).

La encapsulación: Se refiere a la capacidad de agrupar y condensar en un entorno con límites bien-definidos distintos elementos. Cuando hablemos de encapsulación en general siempre nos referiremos, pues, a encapsulación abstracta. De manera informal, primero generalizamos (la abstracción) y luego decimos: la generalización está bien, pero dentro de un cierto orden: hay que poner límites (la encapsulación), y dentro de esos límites vamos a meter, a saco, todo lo relacionado con lo abstraído: no sólo datos, sino también métodos, comportamientos, etc.

Por un lado es una abstracción pues, de acuerdo con la definición establecida anteriormente, es en ésta donde se definen las propiedades y atributos genéricos de determinados objetos con características comunes (recordemos el ejemplo de la sala de cine). La Clase es, por otro lado, una encapsulación porque constituye una cápsula o saco que encierra y amalgama de forma clara tanto los datos de que constan los objetos como los procedimientos que permiten manipularlos. Las Clases se constituyen, así, en abstracciones encapsuladas.

La herencia: Se aplica sobre las clases. O sea, de alguna forma las clases pueden tener descendencia, y ésta heredará algunas características de las clases "padres". Si disponemos las clases con un formato de árbol genealógico, tenderemos lo que se denomina una estructura jerarquizada de clases.

La OOP promueve en gran medida que las relaciones entre objetos se basen en construcciones jerárquicas. Esto es, las clases pueden heredar diferencialmente de otras clases (denominadas "superclases") determinadas características, mientras que, a la vez, pueden definir las suyas propias. Tales clases pasan, así, a denominarse "subclases" de aquéllas.

La herencia se implementa mediante un mecanismo que se denomina derivación de clases: las superclases pasan a llamarse clases base, mientras que las subclases se constituyen en clases derivadas. El mecanismo de herencia está fuertemente entroncado con la reutilización del código en OOP. Una clase derivada posibilita, el fácil uso de código ya creado en cualquiera de las clases base ya existentes.

El concepto de herencia constituye un estrato básico del paradigma de objetos, pero esto no significa que todas las relaciones entre clases en OOP deban ajustarse siempre a este modelo jerárquico. Es necesario establecer si la pretendida relación entre objetos es de pertenencia o de derivación. En una relación típica de pertenencia un objeto contiene al otro

Polimorfismo: Esta propiedad, como su mismo nombre sugiere múltiples formas, se refiere a la posibilidad de acceder a un variado rango de funciones distintas a través del mismo interfaz. O sea, que, en la práctica, un mismo identificador puede tener distintas formas (distintos cuerpos de función, distintos comportamientos) dependiendo, en general, del contexto en el que se halle inserto.

El polimorfismo se puede establecer mediante la sobrecarga de identificadores y operadores, la ligadura dinámica y las funciones virtuales. El término sobrecarga se refiere al uso del mismo identificador u operador en distintos contextos y con distintos significados.

La sobrecarga de funciones conduce a que un mismo nombre pueda representar distintas funciones con distinto tipo y número de argumentos. En el ámbito de la OOP, la sobrecarga de funciones equivale a que un mismo mensaje puede ser enviado a objetos de diferentes clases de forma que cada objeto respondería al mensaje apropiadamente.

La sobrecarga de operadores permite, por otro lado, el desarrollo de un código más coherente, como especialización de la sobrecarga de funciones, posibilitando la re-definición (para tipos de datos definidos-por-el-usuario) de las operaciones realizadas por éstos (+, -, *, >, etc.). Esto es, ocurre lo mismo que en la sobrecarga de funciones, pero aquí, en vez de identificadores de funciones, tenemos operadores.

Gracias a la ligadura dinámica, pueden invocarse operaciones en objetos obviando el tipo actual del éstos hasta el momento de la ejecución del código.
Otros Conceptos

* Agregación: Composición de un objeto por otros. Es una relación más débil que la que existe entre el atributo y el objeto al cual pertenece, y más fuerte que una asociación.
* Concurrencia: Propiedad que distingue un objeto activo de otro inactivo.
* Persistencia: Es la propiedad de un objeto cuya existencia trasciende el tiempo y/o el espacio (ej. el objeto continua existiendo luego de que su creador deja de existir / la ubicación de un objeto se mueve a un espacio de direcciones diferente de aquella donde fue creada).
* Visibilidad: capacidad de restringir el acceso a atributos y servicios de un objeto. Particularmente importante en el diseño e implementación. (ej.: público / protegido / privado).

Leer más...