Está en la página 1de 8

JAVA PARA PROGRAMADORES (4.1).

METODOS Y VARIABLES DE CLASE Y DE


INSTANCIA
LA PROGRAMACIÓN ORIENTADA A OBJETOS (OOP) es un intento de hacer
programas más cercanos al modelo de como las personas piensan sobre ellos, y
como se comportan con el resto del mundo. En el centro de la programación está
la idea es realizar un trabajo, y la programación consiste en encontrar una
secuencia de instrucciones que realicen la tarea. En el centro de la programación
orientada a objetos, hay objetos– entidades que tienen un comportamiento, que
guardan información, y que interactúan con otros. La programación consiste
entonces en diseñar un conjunto de objetos que tengan relación con el problema.
El conjunto de «objetos programas» pueden representar entidades abstractas o
reales en el área de definición del problema. Esto supone el hacer un diseño del
programa mucho más natural, y por consiguiente, más fácil de seguir y de
entender.
Lo más importante de OOP es el cambio total del punto de vista. Cuando
pensamos en objetos en la programación estándar, el término solo significa que
vamos a unir unas cuantas variables con las rutinas necesarias para manejarlas.
De hecho es posible el utilizar las técnicas de la programación orientada a objetos
en cualquier lenguaje de programación.
Sin embargo existe una gran diferencia entre un lenguaje que hace la OOP
posible frente a otro que cuente con un soporte activo. En un lenguaje de
programación orientada a objetos como Java, se incluyen muchas características
que lo hacen totalmente distinto a un lenguaje estándar. Para poder emplear
todas estas características adecuadamente, debe «orientar» su forma de pensar
adecuadamente.
Las clases en Java son plantillas para hacer objetos. Cada objeto pertenece a
una sola clase.
Un objeto es una instancia de una clase.
La clase de un objeto determina qué tipo de datos contiene y cuál es su
comportamiento. Los datos de los objetos se guardan en un juego de variables
que se llaman Instancias variables. Es importante entender que la clase de un
objeto determina qué tipo de variables contiene el objeto, sin embargo, los datos
reales están contenidos en objetos individuales, no en la clase, de esta forma,
cada objeto posee sus propios datos.
Por ejemplo, podría existir una clase llamada Student. La clase puede indicar que
cada objeto del tipo Student incluye una variable llamada name de tipo String.
Puede haber cualquier número de objetos pertenecientes a la clase Student.
Cada uno de esos objetos, por pertenecer a la clase Student deben tener
un name.
El hecho es que cada uno de los objetos Studen tendrán su propio nombre. De
forma similar, si los objetos de la clase Student tienen una variable que representa
las notas de los exámenes, cada uno de los objetos Student tienen su propio
juego de notas.
Adicionalmente a los datos, los objetos también tienen comportamientos. Estos
comportamientos son métodos que pertenecen al objeto. Generalmente estoy
utilizando el termino de «método» para las subrutinas que pertenecen a un objeto
y que representan como se comporta. Estos métodos son instancias de métodos,
porque pertenecen a una instancia de la clase.
Los objetos que pertenecen a una misma clase tienen los mismos métodos , esto
es tienen el mismo comportamiento. Sin embargo, no debe olvidar que las
instancias de los métodos pertenecen a los objetos individuales y no a la clase.
Hay una sutil diferencia entre las instancias de un mismo método en dos objetos
diferentes pertenecientes a la misma clase. El método perteneciente al objeto
tiene un acceso directo a las variables del objeto en particular.Por ejemplo, la
clase Student puede especificar un método instanciable para calcular la nota
global de un estudiante promediando las notas de sus exámenes. Cuando se
llama al método para un objeto concreto de la clase Student usará usará las notas
de ese estudiante tomándolas de las variables del objeto. El mismo método
llamado para un estudiante diferente, usara las notas de ese otro estudiante.
Las clases en Java tienen un doble propósito. Uno de ellos, es justamente el que
se describe: servir como plantilla para hacer objetos. El otro es uno que ya vimos
en anteriores capítulos: mantener agrupadas todas las variables static
relacionadas y todos los métodos static. La regla es que las variables y métodos
static– esto es, que se declaran con el modificador static, pertenecen a la misma
clase y no se crea objeto de esa clase.
Las variables y los métodos non-static no pertenecen del todo a la clase!.En lugar
de eso, hay que especificar que variables y métodos instanciables tendrá la clase.
Todo esto es algo confuso, no hay duda sobre ello, y podemos afirmar que el
diseño de Java en este aspecto, es defectuoso; hubiera sido mejor que asignaran
a estas dos funciones distintas de las clases, dos características distintas del
lenguaje.
Las variables y los métodos static se llaman también variables de clase y métodos
de clase dado que pertenecen a la clase, y no a la instancia de la clase.
Déjeme mostrarle un ejemplo especifico para ver como trabaja todo esto.
Considere esta versión simplificada de la clase Student:
public class Student {

public String name; // Nombre del estudiante

public int ID; // identificador del estudiante (unico)

public double test1, test2, test3; // nota de tres exámenes

public double getAverage() { // Calcular el promedio de nota

return (test1 + test2 + test3) / 3;

private static int nextUniqueID = 1;

public static int getUniqueID() { // devuelve identificador unico

int thisID = nextUniqueID;

nextUniqueID++;

return thisID;

} // Fin de la clase Student

Esta definición de clase dice que un objeto de la clase Student incluirá unas
variables instanciables llamadas name, test1, test2, y test3, e incluirá un
método instanciable llamado getAverage(). Los names, IDs y tests en los
diferentes objetos tendrán, normalmente, valores diferentes. Cuando para un
estudiante en particular se llame al método getAverage()calculará el promedio del
estudiante, usando las notas de sus exámenes.
Por otra parte, nextUniqueID y getUniqueID() son miembros static de la clase
Student. Esto quiere decir que solo hay una copia de la variable nextUniqueID y
pertenece a la clase. De forma similar, getUniqueID esta asociado a la clase, y
no a una instancia particular. No tiene sentido, y puede ser un error de sintaxis,
el que getUniqueID() se refiera a una variable instanciable como name. Un
método static no forma parte del objeto y no tiene accedo directo a las variables
instanciables que están dentro de un objeto.
El método getUniqueID() puede ser llamado desde fuera de la clase usando el
nombre «Student.getUniqueID()» indicando su pertenencia a la clase Student.
Esto se puede hacer tanto si existan como si no existen instancias de la clase .
El método getAverage(), por otra parte, solo puede ser llamado cuando existe
algún objeto de la clase Student. Si std es tal objeto, entonces el método puede
llamarse usando el nombre «std.getAverage()» indicando que el método
pertenece al objeto std las variables instanciables de std pueden ser
mencionadas como std.name, std.ID, std.test1, std.test2, y std.test3.
(Con esto, es posible pensar que un método o una variable static en una clase se
comparte por todas las instancias de la clase. Basado en ese razonamiento, Java
le va a permitir referirse a los miembros static tanto a través de los objetos, como
a través del propio nombre de clase. Esto es, si std es una instancia de la clase
Student es correcto el referirse a std.getUniqueID() en lugar de
Student.getUniqueID(). Sin embargo, pienso que esa sintaxis solo puede
aumentar la confusión y les animo a que la ignoren.
Creo que vale la pena hablar algo sobre la presencia de la variable
static nextUniqueID. Dado que es una variable static solo existe una versión de
esa variable y solo existe mientras el programa esta funcionando.(Las instancias
de las variables, por otra parte, aparecen y desaparecen cuando los objetos se
crean o se destruyen).
Al empezar el programa, se almacena en la variable Student.nextUniqueID el
valor inicial 1. Cada vez que se llama al método static Student.getUniqueID se
incrementa el valor de nextUniqueID. Ahora bien, dado que nextUniqueID como
privado, es completamente inaccesible desde fuera de la clase Student. Podemos
ver todo lo que se puede hacer con esa variable examinando la clase Student.
Esto es la mejor garantía de que solo hay una manera de cambiar el valor de
nextUniqueID y es llamando al método getUniqueID(). Podría ser interesante que
otras variables como las instanciables test1, test2 y test3 tuvieran una protección
similar. Volverá al tema de controlar el acceso a las variables, mas tarde.
Hasta ahora hemos hablado de que los objetos pueden ser creados usando las
clases como plantilla, pero no hemos hablado de como crear los objetos en los
programas. Si tiene una clase, como Student, puede declarar una variable de esa
clase:
Student std; //declarar variable std como de tipo Student
Sin embargo, declarar una variable no crea un objeto.Esto es un punto muy
importante, que queda definido con la siguiente Afirmación Muy Importante:
En Java, una variable no puede almacenar un objeto.
La variable sólo puede almacenar la referencia al objeto.

Debe pensar que los objetos deben estar flotando independientes por la memoria
del ordenador. (De hecho, los objetos viven en una parte de la memoria llamada
heap.) En lugar del objeto en si mismo, lo que se guarda en la variable es la
información necesaria para encontrar ese objeto en la memoria. Esta información
se llama referencia o puntero al objeto. En efecto, la referencia a un objeto es la
dirección de la posición de la memoria donde se almacena el objeto. Cuando usa
una variable tipo objeto, el ordenador emplea la referencia que esta en la variable
para poder encontrar el objeto real.
Los objetos realmente se crean con un operador llamado new, que crea el objeto
y devuelve la referencia al objeto. Por ejemplo, asumiendo que std es una variable
del tipo Student,
std = new Student();
creará un nuevo objeto del tipo Student y guardará la referencia a este objeto
en la variable std. Se puede acceder a las variables y métodos instanciables del
objeto por medio de std,como «std.test1».
Para una variable como std , cuyo tipo esta definido por una clase, el no referirse
a ningún objeto no está inicializada. En ese caso se dice que std guarda una
referencia nula. En Java la referencia nula debe ser escrita como «null». Puede
asignar una referencia nula a la variable std diciendo:
std = null;
y puede comprobar si el valor de la variable es nulo
if (std == null) .. ..

Si el valor de la variable es nulo, como puede suponer, será ilegal el referirse a


una instancia de variable o a una instancia de método, dado que no existe el
objeto, y por lo tanto no hay variables a las que se pueda referir. Por ejemplo, si
el valor de la variable std es nulo, entonces es ilegal el referirse a std.test1.Si su
programa intenta usar una referencia nula, se producirá un error llamado «null
pointer exception».
A continuación, se muestra la secuencia correcta para trabajar con objetos:

Student std = new Student(); // Declara la variable std

// y la inicializa con la

// referencia al nuevo objeto

// creado de la clase Student

Student std1 = new Student();// Declara std1 y la inicializa

// con la referencia a otro

// objeto nuevo.

Student std2 = std1; //Declara std2 y la inicializa

// por lo que se refiere al

// MISMO objeto std1

Studen std3; // Declara std3 y lo inicializa

// a nulo. (automaticamente)

std.name= "John Smith";

std.ID = Student.getUniqueID();

std1.name = "Mary Jones";

std1.ID = Student.getUniqueID();// El resto de la variables instanciables

// tendran como valor cero

Cuando el ordenador ejecuta estas instrucciones, la situación es algo semejante


a esto (asumiendo que las dos llamada a getUniqueID() fueron las dos primeras
veces que se llamo a este método en el programa):
Este dibujo presenta las variables en pequeñas cajas, etiquetadas con el nombre
de las variables. Los objetos se presentan como cajas con los bordes
redondeados. Cuando una variable contiene una referencia a un objeto, el valor
de la variable se presenta como una flecha que apunta al objeto. Las flechas
desde std1 y std2 apuntan al mismo objeto.
Esto ilustra el siguiente Punto Muy Importante
Cuando una variable objeto se asigna a otra, solo se copia la referencia.
El objeto referenciado no se copia.
Esto es muy diferente a la semántica asociada a las instrucciones de
asignación.(Donde los valores se referían a los tipos primitivos de Java, la
asignación obedecía a la semántica esperada. Esto es: cuando se asignaba, se
copiaba el valor entre los tipos primitivos.) Observe que en este ejemplo dado
que a std1.names se le asignó el valor «Mary Jones», también es cierto
que std2.name tiene el valor «Mary Jones». De hecho, std1.name y std2.name son dos
maneras distintas de referirse exactamente a la misma cosa.
Puede utilizar los operadores == y != para comprobar la igualdad o desigualdad
entre dos objetos, pero aquí otra ves la semántica es especial. Cuando hace la
pregunta «if (std1 == std2)» esta comprobando que las referencias de std1 y
std2 apuntan exactamente a la misma dirección de memoria, no esta
comprobando si los valores contenidos en los objetos son iguales.Puede ser
posible tener dos objetos con el mismo valor en una variable instanciable. Sin
embargo, los objetos no se consideraran iguales por el operador ==, porque están
almacenados en distintas direcciones de memoria.
Hay una pequeña sorpresa en la ilustración superior. Ya sabíamos que en Java
las Strings eran objetos.
En particular, es posible que el valor de la string sea nulo. y, en todos los caso,
la variable String solo almacena la referencia a la String no la string en si misma.
Esto explica el por qué el operador == no funcionaba como se esperaba si se
usaba sobre una String (se explicó anteriormente):Dos strings se consideran
iguales por el operador == solo si ambas están almacenadas en la misma
dirección de memoria, no siendo meramente casual, que ambas tengan los
mismos caracteres.
Esto es, si s1 y s2 son dos strings, es posible que s1==s2 sea falso cuando ambas
contienen los mismos caracteres!. Es por esto por lo que debe usar la
comprobación s1.equals(s2) para comprobar si ambas son iguales.

También podría gustarte