Professional Documents
Culture Documents
Un programa orientado a objetos puede ser considerado como un conjunto de objetos que
interactúan entre si para obtener un resultado, al contrario de la programación estructurada que
solo cuenta con un conjunto de subrutinas aisladas de los datos.
Modificadores de acceso
En un diagrama de clase podemos observar a la izquierda de los atributos y métodos un símbolo +,
– y #. Estos símbolos nos indican el nivel de acceso, es decir que esos elementos de la clase
podrán o no ser vistos desde fuera de la clase.
Existen varios niveles de acceso para variables y métodos, cada uno de ellos será empleado
según las necesidades de diseño y programación:
• Los miembros public (públicos) serán vistos desde cualquier punto fuera de la clase, es decir
que puede ser usado o manipulado por cualquier otra clase (programa).
• Los miembros private (privados) estarán únicamente disponibles por los métodos
pertenecientes a la clase, es decir que únicamente sus métodos hermanos pueden accederlos.
• Existen además los modificadores de acceso protegido (protected) y por defecto (default).
UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez
Declaración e implementación
Los miembros public son frecuentemente reconocidos como la interfase del objeto debido a que
son los únicos elementos que pueden comunicarse con otros objetos. Por otro lado, se recomienda
que los atributos sean privados, pues esto asegura el encapsulado, ya que no permitiremos que
tomen valores que puedan poner en riesgo el buen funcionamiento del conjunto (clase). Se
recomienda construir el número necesario de métodos públicos que nos permitan manipular a
estos atributos. En su momento hablaremos de los accessors (getters / setters), métodos que son
los responsables de manipular aquellos atributos privados.
Declaración de clase
Para el diseño de las clases emplearemos la palabra clave class y especificamos el nombre de la
clase, posteriormente declaramos los atributos y métodos dentro del bloque de la clase.
Adicionalmente por el momento emplearemos dos modificadores que nos indicaran el tipo de
acceso a los miembros de la clase, public y private.
La palabra public nos indica que la clase será vista desde cualquier punto, la ausencia del
identificador de acceso indica que la clase únicamente será vista desde un grupo selecto llamado
paquete. Los miembros deben ser definidos dentro del bloque { … } de la clase. Es importante
recordar que todas las variables y funciones en Java deben pertenecer a alguna clase, ya que no
existen variables y funciones globales.
Declaración de atributos
Los atributos miembros declarados dentro de la clase como ya hemos visto son variables de una
clase particular de objeto y representan las propiedades o características más básicas de ese
objeto en particular. Las variables miembro o variables de instancia pueden ser declaraciones de
cualquier tipo de dato existente en Java, incluyendo objetos de cualquier otra clase que este
disponible dentro o fuera del paquete, de tal forma que los atributos miembros de la clase tendrán
modificador de acceso (public, private o default) que le permitirán determinar el tipo de acceso al
que esta disponible.
El atributo miembro suele ser declarado en la parte inicial de la clase justo antes de la declaración
de métodos miembro, así pues, datos miembros estarán disponibles de manera local a todas las
funciones de la clase por lo que no es necesario hacer referencia explicita a ellos, aunque en caso
de que sea muy necesario (resolución de ambigüedad), se emplea el identificador this para
reforzar la referencia.
UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez
class A {
private int a, b, c; // a, b y c son enteras y privadas
public String nombre, apellido; // variables publicas
double arreglo[], valor; // variables por defecto
...
}
Los atributos de la clase solo serán declarados, hasta este punto no es necesario realizar una
inicialización de los datos ya que esta tarea la realizara el constructor de la clase.
Declaración de métodos
La comunicación con un objeto se realiza a través del paso de mensajes. El paso de mensajes es
el término utilizado para referirnos a la invocación de métodos. Los métodos miembros de la clase
son funciones que están relacionadas con un objeto en particular.
En un archivo de programa java es posible definir varias clases, pero no puede haber más de una
clase publica. En caso de definir una clase pública el archivo debe tener exactamente el mismo
nombre de la clase pública, con la extensión .java, por lo que el siguiente código estará presente
en un archivo llamado Main.java.
class Ejemplo
{
private int dato1, dato2, dato3; // datos miembro
public void asignar( int a, int b, int c ) { // método que asigna valores
this.dato1 = a;
this.dato2 = b;
this.dato3 = c;
}
Como podemos observar todos aquellos atributos y métodos que forman parte de una
determinada clase; y que representan sus características y propiedades particulares, encapsulan
estos elementos y los dota de ciertos criterios de visibilidad y manipulación con respecto a otras
clases. Además, la clase Ejemplo es declarada en la parte superior y posteriormente es declarada
una clase publica Main, que es la clase principal que se encargara de la ejecución del programa,
pues implementa el método main que es el responsable de iniciar la ejecución completa del
programa (punto de arranque). Entonces en la clase Main se crea una instancia (objeto) de la
clase Ejemplo a través del operador new para un objeto llamado e de tipo Ejemplo.
UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez
La clase “Main” es la responsable de iniciar el proceso de ejecución pues es una clase publica que
contiene al procedimiento main, de esta manera la clase Ejemplo, contiene todos los elementos de
programación necesarios para ejecutar diversas acciones, así como un conjunto de datos
(propiedades) sobre los cuales realiza ciertas operaciones.
También es posible ver este ejemplo desde otra perspectiva en la cual no existe una clase principal
que funja las acciones de una directora de orquesta, es decir la responsable de la ejecución del
programa, de manera que es posible dentro de la misma clase incrustar la función main que sea la
responsable de la dirección del programa. De manera que solo existirá una sola clase que es la
encargada de realizar todas las acciones. Es importante recordar que ambos programas realizan
las mismas acciones, salvo que se tienen sus elementos distribuidos de una manera distinta, pero
en esencia el resultado es el mismo.
public void asignar( int a, int b, int c ) { // método que asigna valores
this.dato1 = a;
this.dato2 = b;
this.dato3 = c;
}
Note que la clase Ejemplo crea un objeto de la misma clase empleando el operador new, de
manera que manda a llamar al constructor por defecto de la clase, el constructor de la clase
Ejemplo no se encuentra presente de forma específica, ya que el compilador lo introduce. Si en
algún momento el constructor fuera re-implementado, será necesario incrustar el constructor por
defecto de manera específica, si es el caso de que sea necesario en la ejecución.
Las variables o propiedades de la clase también pueden ser accedidas de igual manera con el
operador “.”, aunque esta clase de acceso se determina en base a su nivel de alcance, es decir si
UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez
se trata de datos públicos o privados. Es recomendable tener niveles de acceso en los datos y
funciones ya que esto conlleva a un buen diseño de la clase que pretendamos implementar.
import java.util.Scanner;
class Empleado
{
private int clave;
private String nombre;
private double salario;
Sobrecarga de constructores
Los constructores pueden o no llevar argumentos, y en ningún caso regresan valor alguno, su nivel
de acceso es siempre publico, pues es necesario que se ejecuten desde fuera de la clase cuando
se crea una instancia de una clase. Cuando un constructor no lleva argumentos se le suele llamar
constructor por “default” o por defecto.
En muchos casos un solo constructor no será suficiente para describir el comportamiento completo
de nuestro objeto por lo que será necesario sobrecargarlo, es decir emplear en varias definiciones
de función el mismo nombre de la función constructora, cuidando que difieran el numero y tipo de
argumentos en cada función.
class Complejo {
private double real, imag; // variables miembro
El constructor sin argumentos inicializa el valor de las variables a cero, de manera que estén
disponibles para su uso. El constructor con argumentos recibe un par de valores que son en
realidad los elementos básicos de la clase complejo, tome en cuanta que ambas variables tienen el
mismo nombre (las de argumento y las locales a la clase) por lo que es necesario diferenciar entre
ellas empleando el operador this. El operador this le indica que las variables a las que se refiere
son a las del objeto (propietario de la llamada).
Hay 3 razones por las que se debe de sobrecargar las funciones constructoras:
• Ganar flexibilidad
• Permitir arreglos dinámicos
• Construir copias de objetos.
Así pues, la declaración para objetos de la clase complejo se realizaría de la siguiente manera:
x.imprimir();
y.imprimir();
r.imprimir();
}
}
Podemos observar en la figura que en la memoria de pila (memory stack), se encuentran todas
aquellas variables que hayan sido declaradas dentro de un método (variables locales), incluyendo
a los tipos de datos compuestos como los arreglos y objetos, solo que aquellos considerados como
objetos (arreglos e instancias) almacenan una dirección de memoria (un puntero que resulta
transparente para el programador). De manera que es muy importante recordar que TODO objeto
es una referencia de memoria dinámica que reserva espacio suficiente para las variables de
instancia.
class Empleado {
public int clave;
public String nombre;
public double salario;
public Empleado() {}
this.clave = clave;
this.nombre = nombre;
this.salario = salario;
}
import java.util.Scanner;
Sobrecarga de métodos
Cuando dos o mas métodos comparten el mismo nombre y en tanto difieran en el tipo y/o número
de argumentos, y preferiblemente cada una de ellas contenga un código diferente, se dice que
están sobrecargadas (overloaded). De manera que para obtener la sobrecarga de funciones
simplemente hay que declarar y definir todas las versiones requeridas de la función.
El ejemplo emplea la sobrecarga de funciones tanto estaticas como de instancia. Java se hará
cargo de interpretar el argumento y decidir que función se hará cargo de él.
UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez
public class A
{
public static void main(String [] x){
System.out.println( Sobrecarga.maximo(1,2) ); // método de clase
int [] a = {1,3,2};
System.out.println( Sobrecarga.maximo(a) ); // método de clase
Sobrecarga obj = new Sobrecarga();
System.out.println( obj.abs(-1) ); // método de instancia
System.out.println( new Sobrecarga().abs(-23F) ); // método de instancia
}
}
class Sobrecarga {
public int abs(int x) {
return x > 0 ? x : x*-1;
}
public float abs(float x) {
return x > 0 ? x : x*-1;
}
public static int maximo(int x, int y){
return x > y ? x : y;
}
public static int maximo( int [] array){
int n = array[0];
for( int i = 1; i < array.length; i++)
n = n > array[i] ? n : array[i];
return n;
}
}
Manejo_alumno
Del diagrama podemos inferir varias cosas, requerimos al menos 4 clases, una que defina los
datos relacionados con Alumno, otra para definir los datos de una Materia, además podemos
observar que Alumno requiere un conjunto de materias, además podemos ver que es necesario
contar con un par de clases que se encarguen de recabar la información necesaria de cada
Alumno y Materia, y son necesarias un par de clases que se encarguen de la manipulación.
UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez
Generalmente una clase esta compuesta por un conjunto de atributos los cuales deberán de ser
manipuladas de alguna forma, debido a que los atributos de la clase generalmente se declaran
como privadas y sin por tanto inaccesibles, es necesario que exista un mecanismo que nos permita
su fácil manipualición.
Accessors (getters/setters)
Antes de continuar con el desarrollo del problema de alumnos y materias es necesario definir el
concepto denominado “accessors”, estos se definen como los métodos que son capaces de
interactuar con los atributos privados de una clase, debido a que los atributos son valores
inaccesibles, entonces es necesario contar con mecanismos que interactúen con ellos y se
preserve la encapsulación.
A continuación, se define una clase A con un par de atributos dato1 de tipo int y dato2 de tipo
String, ambos atributos tendrán sus respectivos métodos get y set que se encargarán de
interactuar de manera publica:
class A {
private int dato1;
private String dato2;
Los métodos setAtributo() se encargan de recolectar los datos relativos al atributo en cuestión, así
como los métodos getAtributo() se encargan de recuperar los valores relativos a cierto atributo
generalmente privados o protegidos.
Una vez aclarado el concepto de los métodos de acceso, prosigamos con el planteamiento
relativo al problema de los Alumnos y las Materias.
Para ello se plantea recolectar la información necesaria para un alumno, así como para el conjunto
de materias que cursa, en este caso el alumno además de sus datos cuenta con un arreglo de
materias donde almacenará la información relativa a cada materia que cursa, para este caso se
consideran 4 materias aún que el modelo se presta para que sea un numero variable empleando
listas ligadas. De momento conservaremos esta idea con arreglos para poder comenzar a
modelarlo.
La lista de cada método getter y setter correspondiente a cada atributo de la clase Alumno, así
como para la clase Materia se muestra a continuación:
public Alumno() {}
UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez
Las materias están organizadas de la siguiente manera: se cuenta con el nombre, el número de
créditos, la calificación y el número de faltas, observe la declaración de cada getter y setter según
el atributo que le corresponda.
public Materia() {}
Una vez desarrolladas las clases responsables de la recolección de los datos, procedemos a crear
las clases que se encargaran de recolectar la información relativa a esos datos, en primer lugar,
generaremos la clase Manejo_alumno responsable de interactuar con el usuario final pues
realizará los procesos de captura y despliegue de alumnos, para ello genera un arreglo que se
asocia a un elemento llamado grupo. Suponemos que un grupo es una colección homogénea de
individuos de allí el uso del arreglo. Se supone que al constructor le indicaremos el número de
alumnos asociados a un grupo.
import java.util.Scanner;
}
}
}
import java.util.Scanner;
import java.util.Scanner;
public class Sistema {
public static void main(String[] args) {
System.out.print("Cuantos alumnos serán ?");
Scanner in = new Scanner(System.in);
int tamano = in.nextInt();
Manejo_alumno objeto = new Manejo_alumno(tamano);
objeto.capturar();
objeto.mostrar();
objeto.ordenar();
System.out.println("*** ORDENADO ***");
objeto.mostrar();
}
}
La idea principal en éste ejemplo es mostrar la forma en como se realiza la programación orientada
a objetos para problemas cotidianos, aquí tratamos de usar al máximo el concepto de orientación a
objetos ya que se construyen objetos bien definidos de diversas clases que interactúan entre sí
transmitiendo mensajes de un objeto a otro.
Ejemplos
En laboratorio
Home/paquete
datos/
Main.java
/* Main.java
* importamos las clases del paquete datos para que estén presentes */
import datos.*;
UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez
Home/paquete/datos
/* A.java
* la sentencia packaged indica que la clase A habitara en el vecindario
de datos (directorio)*/
package datos;
public class A {
int porDefecto; // será accesible por el paquete datos
public int publico;
private int privado;// manipulado por objetos de la clase A dentro del paquete
}
/* B.java
* la sentencia package indica que la clase B habitara en el vecindario
de datos (directorio)*/
package datos;
public class B
{
A obj;
public void metodo() {
A obj = new A();
obj.porDefecto = 4; // es accesible pues viven en el mismo paquete
obj.publico = 5;
obj.privado = 6; // accesible dentro del paquete por objetos de A
}
}
Podemos concluir entonces que los elementos declarados de tipo default (sin nivel de acceso)
únicamente serán visibles dentro del directorio o paquete donde fueron declarados.
A continuación un ejemplo de su declaración y uso, suponga que se requiere una clase Nave, que
será la responsable de crear tantos objetos tipo Nave como sea necesario para un juego de video.
De tal manera que será necesario tener una variable que sea la responsable de llevar el conteo del
numero total de naves existentes, de tal manera que al momento de que sean destruidas se
decrementa el numero de naves a seran visualizadas.
UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez
class Nave
{
private int x,y; // coordenadas
private String nombre; // nombre de la nave
private int serie;
private static int count = 0; // variable de clase
Aún cuando los datos miembro static parezcan variables globales, estos tienen alcance de clase.
Los miembros static pueden existir aún si no se tienen ningún objeto de la clase, el acceso a estos
miembros debe ser a través de la clase misma, NombreClase.datoEstatico. Para el caso de
nuestro ejemplo no es accesible ya que cuenta con un modificador privado que impide su acceso.
También es posible crear funciones static, que resultan muy utiles cuando se trata de usarlar para
una tarea especifica donde no se vean involucrados los miembros del objeto, a estos métodos se
les conoce como métodos de clase y se referencian de la misma forma que las variables static,
NombreClase.metodoEstatico.
UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez
• Deben utilizarse varias instancias a1, a2, ... etc. de la misma clase.
• Los objetos de la clase A no pueden tener existencia independiente más que como miembros
de la clase contenedora B.
class B
{
public class A { // clase anidada (clase miembro)
...
}
A a1, a2, a3; // Ok. B contiene objetos tipo A
...
}
El identificador de una clase anidada está sujeto a las mismas reglas de acceso que los restantes
miembros. Si una clase anidada se declara en la sección private de la clase circundante, la clase
anidada será utilizable sólo por los miembros datos de la clase que la circunde.
En caso de que la clase miembro sea public podrá ser accedida atreves de la clase que la
contiene empleando el operador de acceso a miembros: clase.subclase.
A continuación, un ejemplo del uso de clases anidadas; en esencia se verá que es un efecto muy
similar a emplear el esquema de estructuras. Es recomendable el uso de este tipo de esquemas
anidados de forma correcta y justificada.
Diseñaremos una clase que emplea clases anidadas, declararemos un vector de tipo Datos que
manipulara los datos estadísticos de una ciudad y el número de robos en esa ciudad. Los objetos
Histogram podrán capturar datos relativos al nombre de una ciudad y el número de robos en ella,
posteriormente mostrará los datos en forma de tabular y el número de robos para cada ciudad será
expresado adicionalmente con un histograma.
• Histogram( int ): método constructor que recibe como parámetro el numero de casillas que
se habilitaran para los datos del vector dinámico. El constructor se encargara de realizar el
ciclo para definir el tamaño del vector y asignará valores iniciales a cada componente del
vector.
• mostrar( ): método encargado de mostrar los datos del vector y el histograma relativo a la
frecuencia de robos en cada entidad.
import java.util.Scanner;
class Histograma
{
private Datos [] vector; // vector de estructuras
private class Datos { // crea la estructuras con una clase
public String ciudad;
public int frecuencia;
public Datos() {}
}
Histograma( int x ) {
this.vector = new Datos[x];
for (int i = 0; i < this.vector.length; i++)
this.vector[i] = new Datos();
}
La siguiente clase Romano emplea un mecanismo anidado para definir un arreglo de clases tipo
Tupla, encargado de almacenar la información relativa a los valores que representan cada
elemento involucrado en la generación del numero romano.
class Romano {
private String romano;
private int arabigo;
public Romano() {}
/* recorre el vector buscando restar el valor correspondiente a cada
número e ir concatenando el valor en romano según sea el caso */
public Romano(int numero) {
StringBuffer cadena = new StringBuffer();
for(int i = 0; i < tabla.length; i++)
while (tabla[i].numero <= numero){
cadena.append(tabla[i].letra);
numero -= tabla[i].numero;
}
this.romano = cadena.toString();
}
Para recorrer una lista enlazada circular podemos empezar por cualquier nodo y seguir la lista en
cualquier dirección hasta que se regrese hasta el nodo original. Desde otro punto de vista, las listas
enlazadas circulares pueden ser vistas como listas sin comienzo ni fin. Este tipo de listas es el más
usado para dirigir buffers para “ingerir” datos, y para visitar todos los nodos de una lista a partir de
un nodo dado.
raíz
info sig info sig info sig
primero último
this.tamano--;
return tempo;
}
Bibliografía
1. Grover, Radhika S., Programming with java: A multimedia approch, Jones and Bartlett
Publisher, 2013, ISBN: 9781449638610.
2. Paul J. Deitel, Harvey Deitel, JAVA: ¿Cómo programar?, 9a edición, Pearson Educación, 2012,
ISBN: 9786073211505