Diferencia entre revisiones de «Prog. Fundamentos Programación Orientada a Objetos (POO)»

De MediaWiki
Ir a la navegación Ir a la búsqueda
Línea 797: Línea 797:
  
  
 +
* Si tratamos de compilar la clase Beta, diremos que el atributo (variable) soyPrivado no es accesible.
 +
: Para poder modificar o leer el valor de la variable soyPrivado, necesitaríamos implementar dos métodos, uno que nos devuelva el valor y otro que le asignase un valor enviado como parámetro.
 +
: ¿Cuál es la ventaja de esto? Que controlamos los valores que queremos asignar a la variable y, por lo tanto, hacemos que nuestra clase sea más robusta, es decir, que sea más difícil que falle.
  
 +
 +
* Por ejemplo:
 +
 +
[[Imagen:Prog_fund_poo_14.jpg|600px|center]]
 +
 +
* Ahora la temperatura (variable temp) tendrá el valor de 10 que asignaremos previamente.
 +
: Como podemos ver, el método asignarValor controla que nunca pasamos un número negativo y si lo pasamos por error asignará un valor predeterminado (valor 0)
 +
: Aunque la variable se declara como privada, los métodos 'asignarValor' y 'devolverValor' son públicos y van poder se llamados desde la otra clase a través del objeto 'a'.
 +
 +
 +
 +
 +
* Continuemos con nuestro ejemplo:
 +
: Supongamos que los españoles necesitan un método que informe cuánto debe pagar a hacienda por la cantidad de dinero ganado.
 +
: Por lo tanto, declararemos un método de nombre, pagarHacienda con un parámetro de entrada que nos informará de la cantidad ganada.
 +
: Como es un método que solo afecta a los españoles, lo declararemos en la clase de español y no en otro. Este método devolverá el dinero a pagar.
 +
 +
* El proceso de este método es el siguiente:
 +
 +
:* Si la cantidad es > 1000, el importe a pagar se calcula de la siguiente manera:
 +
::: Cantidad / GC_COEFICIENTE_1
 +
:* Si la cantidad es <= 1000, entonces el importe a pagar se calcula de la siguiente manera:
 +
::: Cantidad / GC_COEFICIENTE_2
 +
 +
: GC_COEFICIENTE_1 valor constante: 10.12
 +
: GC_COEFICIENTE_1 valor constante: 11.33
 +
 +
* <u>Recuerda:</u> Para crear una constante en Java, el modificador '''final''' debe preceder a la declaración y por convenio el nombre debe ir con letras mayúsculas y si tiene varias palabras, separadas por guión bajo.
 +
: Ejemplo: final int CONSTANTE = 10;
 +
 +
 +
 +
 +
* '''Ejercicio:''' implementar este método.
 +
::<syntaxhighlight lang="java" line enclose="div" highlight="3-4,6-12" >
 +
public class Espanol extends Europeo {
 +
    String nif;
 +
    final float GC_COEFICIENTE_1 = 10.12f;
 +
    final float GC_COEFICIENTE_2 = 11.33f;
 +
   
 +
    public double cantidadPagar(int cantidade) {
 +
        if (cantidade < 1000) {
 +
            return (cantidade / GC_COEFICIENTE_1);
 +
        } else {
 +
            return (cantidade / GC_COEFICIENTE_2);
 +
        }
 +
    }
 +
   
 +
    public void impNif() {
 +
        System.out.println("Nif:" + nif);
 +
    }
 +
 +
    @Override
 +
    public void impMaximosIngresos() {  // imprime el ingreso máximo en pesetas
 +
        System.out.println("Los ingresos máximos son" + maximosIngresos * 166 + " pesetas");
 +
    }
 +
}
 +
 +
</syntaxhighlight>
 +
 +
 +
 +
* '''Pregunta:''' ¿ Qué problema tiene este método si creamos una instancia (objeto) de la clase de Gallego ?
 +
 +
 +
 +
 +
 +
 +
 +
<br />
 +
 +
* '''Solución:''' Ese objeto heredará el método por lo cual podría llamarlo de la forma:
 +
 +
:: Gallego gallego1 = new Gallego();
 +
:: System.out.println("Cantidad a pagar por 1000:" + gallego1.cantidadPagar(1000));
 +
 +
 +
: Y esto no queremos que suceda, ya que la clase Gallego no debería 'heredar' este método, solo los españoles que no son gallegos.
 +
: ¿ Cómo resolver el problema ?: Declarar este método como privado. Entonces no serás heredado por las subclases y por lo tanto no podría llamarse desde la clase Gallego.
 +
: Pero al implementar esta solución encontramos el problema de que ni el método es visible para el objeto de la clase de Espanol.
 +
: Por lo tanto, la solución sería definirlo en la clase de Gallego, pero no devolverá el valor.
 +
: Es decir, en la clase de Espanol:
 +
::<syntaxhighlight lang="java" line enclose="div" highlight="" >
 +
public double cantidadPagar(int cantidad) {
 +
  // CÓDIGO
 +
}
 +
</syntaxhighlight>
 +
y en la clase gallega:
 +
::<syntaxhighlight lang="java" line enclose="div" highlight="" >
 +
public double cantidadPagar(int cantidad) {
 +
}
 +
</syntaxhighlight>
 +
 +
: <u>Nota:</u> Todos estos conceptos se usan nuevamente en el ejercicio 'Un programador novato'.
 +
 +
 +
=Organización de las clases=
 +
 +
 +
* '''Jeráquica''': Todas las clases provienen de la clase Object. La clase Object se encuentra en parte más alta del árbol de herencia en el entorno de desarrollo de Java.
 +
: Todas las clases del sistema Java son descendientes (directos o indirectos) de la clase Object. Esta clase define los estados y comportamientos básicos que deben tener todos los objetos, como la capacidad de comparar
 +
un objeto con otro, de convertirse en cadenas, de devolver la clase a la que pertenece un objeto,...
 +
 +
* '''Física''': Cada paquete en Java hace referencia a las clases que se encuentran en un mismo directorio. Los paquetes son grupos relacionados de clases e interfaces y proporcionan un mecanismo para manejar un gran número de clases e interfaces y evitar conflictos de nombres. Además de los paquetes que proporciona Java, puedes crear tus propios paquetes y guardar en ellos tus propias clases e interfaces, utilizando la sentencia 'package'.
 +
 +
 +
 +
* Supongamos que se está implementando un grupo de clases que representan una colección de objetos gráficos como círculos, rectángulos, líneas y puntos.
 +
: Podrás empaquetarlas en un paquete, por ejemplo, 'gráficos' y entregar el paquete a otros programadores (junto con la documentación de referencia).
 +
 +
* De esta manera, otros programadores pueden determinar fácilmente cuales son tu grupo de clases, como utilizarlas, y cómo relacionarlos entre sí y con otras clases y paquetes. Los nombres de las clases no tienen conflictos con nombres de clases en otros paquetes porque las clases y las interfaces dentro de un paquete son referenciadas dentro de su paquete (técnicamente un paquete crea un nuevo espacio de nombres).
 +
Un paquete se declara usando la sentencia 'package':
 +
 +
[[Imagen:Prog_fund_poo_15.jpg|500px|center]]
 +
 +
* La primera línea del código anterior crea un paquete llamado '''graphics'''. Todas las clases e interfaces definidas en el archivo que contiene esta sentencia son miembros del paquete.
 +
: Por lo tanto, Draggable, Circle y Rectangle son miembros del paquete graphics.
 +
 +
 +
* Los archivos .class generados por el compilador al compilar el archivo anterior que contiene la definición de las clases Draggable, Circle y Rectangle deben ubicarse en un directorio llamado 'graphics' en algún lugar de la ruta '''CLASSPATH'''.
 +
 +
* '''CLASSPATH''' es una lista de directorios que indica a Java donde se encuentran las clases e interfaces compilados. Cuando busca una clase, el intérprete de Java busca el directorio actual y en su CLASSPATH un directorio cuyo nombre coincida con el nombre del paquete del que la clase es miembro.
 +
: Los archivos .class para todas las clases y las interfaces definidas en un paquete deben estar en ese directorio del paquete.
 +
: Los nombres de los paquetes pueden contener subpaquetes (paquetes dentro de paquetes) (separados por punto). De hecho, los nombres de los paquetes Java tienen varios componentes: java.util, java.lang, etc ...
 +
: Cada componente del nombre del paquete representa un directorio en el sistema de archivos. Por lo tanto, los archivos .class de java.util están en un directorio llamado 'util' dentro de otro directorio llamado 'java' en algún lugar en CLASSPATH.
 +
 +
* Para usar las clases en un paquete, utilizamos la '''importación''' antes de la definición de la clase.
 +
: Veámoslo en el siguiente ejemplo:
 +
 +
: "Hmm", dice el programador novato, "tengo un problema. El coordinador del equipo de diseño me dijo que usaría la '''clase Calendar''' para ver la fecha y hora actual en mi aplicación, pero Java no parece entender la clase Calendar,
 +
: Me informa de un error cada vez que trato de usarla...".
 +
 +
[[Imagen:Prog_fund_poo_16.jpg|500px|center]]
 +
 +
 +
* "Esto se debe a que la clase 'Calendar' es parte del paquete de utilidades de Java y tienes que importar ese paquete antes de que pueda usarlo ".
 +
: "¿Importarlo?", Pregunte al programador.
 +
 +
* Las clases que creó Sun se almacenan en bibliotecas de clase llamadas "paquetes". Para que una clase de un paquete esté disponible y pueda ser utilizada en otra clase, se debe <u>importar el paquete</u>, lo que significa que el compilador localizará ese paquete.
 +
 +
: Por defecto, solo las clases básicas de Java están disponibles, aquellas que se encuentran en el paquete java.lang.
 +
: El compilador importa automáticamente el paquete java.lang, pero para usar el resto de las clases que vienen con Java tendrás que importarlas con la '''sentencia import'''.
  
 
::<syntaxhighlight lang="java" line enclose="div" highlight="" >
 
::<syntaxhighlight lang="java" line enclose="div" highlight="" >
 +
import [paquete [.packet2 ...].]nombre de clase;
 
</syntaxhighlight>  
 
</syntaxhighlight>  
 +
 +
: Para separar los diferentes subpaquetes (ya que podemos crear clases en un paquete que se encuentren dentro de de otro paquete) hay que colocar un punto ('.') entre el paquete y los subpaquetes.
 +
Los paquetes de Java estándares se almacenan en un paquete grande llamado java, por lo que el paquete de utilidad se llama realmente java.util (hay otros paquetes grandes disponibles, por ejemplo, el paquete swing se almacena en el
 +
paquete java.swing).
 +
 +
 +
* En el ejemplo anterio de la clase Calendar, tendríamos que escribir el siguiente código:
 +
::<syntaxhighlight lang="java" line enclose="div" highlight="3" >
 +
package POO;
 +
 +
import java.util.Calendar;
 +
 +
 +
public class Principal {
 +
 +
   
 +
    public static void main(String arg[]) {
 +
 +
        System.out.printf("Fecha actual %s",java.util.Calendar.getInstance().getTime());
 +
    }
 +
 +
 +
}
 +
 +
</syntaxhighlight>
 +
 +
 +
* Si quisiéramos 'importar' todas las clases de un determinado paquete, pondríamos '*' de la forma: import java.util.'''*''';
 +
: Normalmente no deberíamos hacer uso de esta opción, ya que, aunque a nivel de rendimiento no supone ninguna diferencia, si que da problemas de claridad y problemas con clases que tengan el mismo nombre y que se encuentren en diferentes paquetes.
 +
:* De claridad ya que no sabemos de que paquete proviene una clase que estemos utilizando en nuestro programa (podríamos tener varios import con *).
 +
:* De 'choque' entre clases que se puedan llamar igual pero que estén en diferentes paquetes.
 +
:: Por ejemplo:
 +
:::java.lang.reflect.Array
 +
:::java.sql.Array
 +
 +
 +
* En caso de no utilizar la sentencia 'import' podríamos utilizar la clase, pero tendríamos que referenciarla con su nombre completo.
 +
: En el ejemplo anterior: System.out.printf("Fecha actual %s",'''java.util.Calendar'''.getInstance().getTime());
 +
 +
 +
 +
  
  

Revisión del 11:02 29 oct 2017

Introducción

  • Antes del paradigma de la POO se utilizaba la programación estructurada.
Este tipo de programación se basa en un diseño descendente (metodología top-down) y se utilizan para implementar los programas tres estructuras básicas: secuencial-condicional-repetitiva.
El programa consistía normalmente en un único archivo donde se encontraba todo el código fuente que daba una solución informática al problema del mundo real, en el que los datos se declaraban a nivel 'global' y definimos un conjunto de funciones, el que se trataban dichos datos y se informaba al usuario.
Este es un tipo de programación orientado al tratamiento de datos, a los procedimientos.
Cuando diseñas un programa utilizando este tipo de metodología piensas en las operaciones y partiendo de ellas, diseñas el programa.
Por ejemplo, si quiero dar una solución informática a la gestión de un centro de enseñanza, podría pensar (metodología top-down):
  • Necesito una gestión de los alumnos del centro.
  • Necesito una gestión de los profesores del centro.
  • Dentro de la gestión de alumnos tendré:
  • Alta => función que pida los datos y los añada
  • Baja => función que pida un identificador y de baja
  • Modificación => función que pida los datos y los modifique
  • Consulta => función que busque datos en base a diferentes criterios.
  • Dentro de la gestión de profesores tendré:
  • Alta => función que pida los datos y los añada
  • Baja => función que pida un identificador y de baja
  • Modificación => función que pida los datos y los modifique
  • Consulta => función que busque datos en base a diferentes criterios.


Los datos estarán definidos a nivel global, utilizando una estructura adecuada para guardarlos, como los arrays.



  • En el paradigma de la POO, el diseño se realiza en base a los datos y utilizando un concepto mucho más 'humano' como es el de objeto.
Un objeto es cualquier cosa que puedas identificar en el mundo real o que puedas a llegar a identificar utilizando la abstracción.
Ejemplo de objetos:
  • Un coche Opel negro matrícula 1234-ABC
  • Una matriz matemática
  • Un globo de color verde que lleva un niño
  • El ordenador con el que estás trabajando
En la POO cada de las características que posee un objeto se denomina atributo (en la Prog. Estructurada se llaman variables).
Todos los objetos 'coches' tienen un conjunto de atributos comunes (matrícula, km recorridos, color,....) por lo que en programación, para poder crear esos objetos utilizamos otro concepto denominado clase.
Una clase define todos los atributos que van a tener los objetos, pero no sus valores, sino los tipos y nombres de los atributos.
Así puedo definir:
  • Una clase Coche que tenga los atributos 'matrícula', 'km', 'color', 'estado'
  • Una clase Matriz que tenga los atributos 'fila','columna'
  • Una clase Globo, que tenga los atributos 'color','tamaño'
  • Una clase Computador que tenga los atributos 'cpu','hd','memoria','velocidadActual'


En una clase, a parte de definir los atributos, también se definen las funciones (métodos en la POO) que se pueden aplicar a los datos definidos en esa clase.
Por ejemplo:
  • La clase Globo puede tener un método 'hinchar' y otro 'deshinchar' que modificará el valor del atributo 'tamaño'.
  • La clase Coche puede tener un método 'recorrer' que modifique el valor del atributo 'km', un método 'arranca','parar','acelerar','frenar' que cambie el atributo 'estado'.
  • La clase Matriz puede tener un método 'sumar' para que modifique el valor del atributo 'matriz'.
  • La clase Computador puede tener un método 'cambiarVelocidad' que modifique el valor del atributo 'velocidadActual'.


En el ejemplo anterior de un centro de enseñanza, si aplicamos esta metodología tendríamos:
  • Una clase 'Alumno' que representaría cada uno de los alumnos
  • Con un método 'crear' que guardaría los datos de un nuevo alumno.
  • Con un método 'modificar' que modificaría los datos de un alumno.
  • El método 'eliminar' no sería necesario en esta clase ya que cuando un objeto no se utiliza, Java lo elimina con el proceso 'garbage collection'.
  • Una clase 'Profesor' que representaría cada uno de los profesores.
  • Con un método 'crear' que guardaría los datos de un nuevo profesor.
  • Con un método 'modificar' que modificaría los datos de un profesor.
  • El método 'eliminar' no sería necesario en esta clase ya que cuando un objeto no se utiliza, Java lo elimina con el proceso 'garbage collection'.
  • Una clase Centro que representaría el centro donde trabajan y estudian los alumnos y profesores.
Dentro de esta clase definiríamos:
  • Un atributo que guardaría un array de 'objetos Alumnos' que representa todos los alumnos del centro.
  • Un atributo que guardaría un array de 'objetos Profesores' que representa todos los profesores del centro.
  • Un método 'crearAlumno' que crearía un nuevo objeto Alumno (llamando al método crear) y lo añadiría al array de Alumnos.
  • Un método 'crearProfesor' que crearía un nuevo objeto Profesor (llamando al método crear) y lo añadiría al array de Profesores.
  • Un método 'eliminarAlumno' que borraría un objeto Alumno del array de Alumnos.
  • Un método 'eliminarProfesor' que borraría un objeto Profesor del array de Profesores.
  • Un método 'modificarAlumno' que en base a un identificador (por ejemplo el nif) buscaría el objeto alumno dentro del array de Alumnos y llamaría al método 'modificar' de ese objeto.
  • Un método 'modificarProfesor' que en base a un identificador (por ejemplo el nif) buscaría el objeto profesor dentro del array de Profesores y llamaría al método 'modificar' de ese objeto.
  • Un método 'listarAlumnos' que en base a un criterio (nombre, nif,...) recorra el array de Alumnos, mostrando aquellos objetos cuyo criterio coincida con los valores guardados en cada uno de los objetos.






POO


Conceptos

Clases

  • Una clase es un conjunto de datos y métodos que manejan esos datos.
  • Los datos y los métodos definen las características de algún tipo de objeto.
  • Por ejemplo, podemos describir un círculo por su punto (x,y) de su centro y por el valor de su radio.
Cada círculo es diferente de los demás (en el centro o en el radio), pero como clase, todos los círculos tienen una serie de propiedades que sirven para dar una definición de círculo.
Es decir, una clase consta de métodos (procedimientos) y atributos (variables), que se encuentran relacionados formando un todo que llamamos clase.


  • Importante:
  • El nombre de las clases en Java debe comenzar con la primera letra en mayúsculas y las siguientes primeras letras de cada palabra si tuviera más de una. Por ejemplo: ChaletsAdosados
  • El nombre debe estar en singular


  • En Java, la creación de una clase se lleva a cabo en dos pasos: la declaración de clase y su definición.


  • La declaración general de una clase es la siguiente:
 1 access class Nombre_Clase [extends NombreClase] [implements NombreClase,....] { // Comienzo del código de la clase
 2 
 3   [access] [static] tipo variable_de_instancia1;    // Declaramos variables
 4   .....
 5   [access] [static] tipo variable_de_instanciaN;
 6   .....
 7 
 8   [access] [static] tipo método1 (lista de parámetros) {   // Declaramos métodos
 9      .....
10   }
11      .....
12   [access] [static] tipo métodoN (lista de parámetros) {
13      .....
14   }
15 } // Fin del código de la clase
Más adelante veremos qué significan todas estas palabras clave ...
Por ejemplo:
1 public class Alumno{
2   String nif;
3   byte edad;
4 
5   public void mostrarEdad(){....}  // Imprime la edad
6 
7 }  // Fin de la clase



Objetos

  • Una vez que se ha definido la clase del círculo, se pueden hacer cosas con ella.
Para usar los métodos y acceder a los métodos datos, se necesita un círculo específico, no sirve la clase; se requiere una instancia de la clase: un objeto Círculo.
La diferencia entre clase y objetos se puede ver al comparar un molde para hacer cookies con las cookies. El molde tiene todas las características de las cookies, pero no es ninguna galleta en particular.
Cada cookie (objeto) es una instancia de la clase de cookie (molde). El proceso de crear un objeto de una clase se llama instanciar.


  • Cada objeto tendrá un estado que estará conformado por los valores de sus atributos en un momento determinado.



Métodos

  • Los métodos son funciones que pueden llamarse dentro de la clase o por otras clases.
Son las acciones que se pueden realizar con un objeto dado.
Hay muchas cosas que se pueden hacer con círculos: calcular un circunferencia, el área, ver si un determinado punto está dentro o fuera, etc.


  • Los métodos definen el comportamiento de un objeto.
Dependiendo a que clase pertenezca el objeto tendrá un comportamiento u otro.


  • Constituyen la interfaz del objeto, es decir, la forma que tienen otros objetos o clases de comunicarse con un objeto y pedirle información o que realice cierta acción.

Programando clases-objetos-métodos

Para aclarar todos estos conceptos, llevaremos a cabo el siguiente ejercicio.
Supongamos que queremos implementar la siguiente clase:
Prog fund poo 1.jpg
Esta clase tiene dos atributos (variables) que son el nombre y la edad.
La forma de definir Java en esta clase es la siguiente:
1 public class Europeo { // Comienza el código de la clase 
2 
3 
4 
5 } //Termina el código de la clase
  • Nota: La clase tiene un modificador de acceso público (public) para indicar que la clase puede ser utilizada por otras clases. Más adelante revisaremos estos conceptos.
En nuestro caso, la clase Europeo tiene dos variables, que deben definirse.
Para definir una variable dentro de una clase de la manera más simple: Tipo nombre_de_variable;
En nuestro caso:
1 public class Europeo { // Comienza el código de la clase 
2   String nombre;
3   int edad;
4 
5 
6 } //Termina el código de la clase


  • Recuerda: Las variables 'miembro' (las que están definidas a nivel de clase) sí se inicializan si no les damos un valor inicial. Si son de tipo numérico se inicializan a 0, si son booleanas a false y si son de referencia o cadena se inicializan a null.
  • Recuerda: Las variables 'miembro' son 'visibles' (se puede acceder a su valor) en toda la clase.


  • En este momento, hemos definido el molde de las cookies.
Es decir, definimos la clase, pero esta clase no tiene ningún valor concreto para los atributos nombre y edad.
Los valores concretos están asociados con los objetos.
Prog fund poo 2.jpg


  • Importante: Una vez que nuestra clase está escrita, es necesario guardarla en un archivo con el mismo nombre de la clase pública, en nuestro caso Europeo y extensión .java.
Dentro de un único archivo físico, podemos haber definido varias clases. Pero de todos ellas, solo una puede tener el modificador 'public' y el archivo físico deben tener el mismo nombre que esa clase.
Prog fund poo 3.jpg


  • Si no estuviéramos en el NetBeans tendríamos que 'compilar' esta clase con la orden: javac (ya visto anteriormente).


  • Crearemos en Netbeans una clase de nombre 'Principal' que tenga el método main definido de la forma:
 1 package aprendiendo;
 2 
 3 /**
 4  *
 5  * @author clase
 6  */
 7 public class Principal {
 8 
 9     /**
10      * @param args the command line arguments
11      */
12     public static void main(String[] args) {
13         // TODO code application logic here
14     }
15     
16 }

Nota:> El nombre del paquete será diferente al vuestro.


  • Ahora, el objetivo es usar la clase Europeo dentro de la clase Principal.
Para esto crearemos (instanciaremos) 3 objetos de la clase Europeo con los siguientes datos:
Prog fund poo 4.jpg


  • ¿Cómo definimos un objeto? Para esto debemos definir un objeto de la misma manera que uno se define variable: Nombre_clase nombre_objeto;
En nuestro caso:
1 Europeos europeos1; // primer objeto 
2 Europeos europeos2; // segundo objeto 
3 Europeos europeos3  // tercer objeto


  • Este es un primer paso, pero a mayores, debemos asignar memoria a estos objetos.
Para esto, se usa el operador new, que reserva la memoria.
Este operador sería equivalente al malloc de C.
En Java no hay operador opuesto, es decir, la liberación de memoria (free en C).
Lo máximo que podemos hacer es asignar un objeto al valor nulo y es Java que a través del proceso de recolección de basura (proceso especial, garbage collection) es responsable de liberar la memoria que ya no es utilizada por ningún objeto.

En nuestro caso:

1 europeo1 = new Europeo();  // reservamos memoria 
2 europeo2 = new Europeo();  // reservamos memoria 
3 europeo3 = new Europeo();  // reservamos memoria


  • El proceso de reservar memoria se llama instanciación.
Estas operaciones se pueden hacer a la vez (definición e instanciación):
1 Europeo europeo1 = new Europeo();
En esta línea, estamos haciendo 3 operaciones:
  • Una declaración: declaramos europeo1 de tipo Europeo.
  • Una instanciación: reservamos memoria con el operador new.
  • Inicialización: más adelante veremos que cuando realizamos la creación de instancias llamamos a uno método especial (procedimiento) llamado constructor que permite inicializar todas las variables. Por defecto, ya vimos que estar variable se inicializan.
  • En este momento tenemos 3 objetos de la clase europea y, por lo tanto, cada objeto tendrá los mismos atributos que la clase a la que pertenece, en este caso dos atributos (nombre y edad).


  • ¿ Cómo asignamos valores a ditas variables ?
De la forma: obxecto.atributo = valor;
En nuestro caso:
1 europeo1.nome = “Angel”;
2 europeo1.idade = 20;
3 europeo2.nome = “Pepe”;
4 europeo2.idade = 15;
5 europeo3.nome = “Jean”;
6 europeo3.idade = 17;


  • El código completo quedaría así:
 1 public class Principal {
 2   public static void main(String arg[]) {
 3 
 4       Europeos europeo1 = new Europeo();
 5       Europeos europeo2 = new Europeo();
 6       Europeos europeo3 = new Europeo();
 7 
 8 
 9       europeo1.nome = “Angel”;
10       europeo1.idade = 20;
11       europeo2.nome = “Pepe”;
12       europeo2.idade = 15;
13       europeo3.nome = “Jean”;
14       europeo3.idade = 17;
15   }
16 }


  • Pero antes de poder compilar esta clase, es necesario resolver el siguiente problema. Como discutimos anteriormente, en Java, todas son clases. En nuestro caso, estamos utilizando la clase Europeo en la clase Principal.
  • Por lo tanto, es necesario informar al compilador de Java que utilizaremos una clase.
Por defecto, Java busca las clases que se encuentran en el directorio actual (en la compilación), por lo que si está en ese directorio, no es necesario hacer nada más.
En Netbeans estaréis creando las clases en el mismo paquete, pero recordar que un paquete tiene una traducción 'física' en forma de directorio, por lo que todas las clases que se encuentren dentro del mismo paquete se pueden referenciar.


  • Veremos más adelante que existe una sentencia import que se utiliza para indicar a una clase que pueda hacer uso de otras clases que están en otros paquetes (grupo de clases relacionadas).
  • En el lenguaje Java, todas las clases se encuentran dentro de un paquete. Si no ponemos ningún paquete en su definición, Java las crea en el paquete por defecto.


  • El paquete java.lang y el paquete actual se importan de forma predeterminada o el paquete por defecto (las clases que se encuentran en el directorio actual).
  • Si no estuviéramos en el entorno NetBeans, desde consola tendríamos que indicarle a nuestra clase (cuando la compilemos) a dónde tiene que ir a buscar físicamente las clases que vamos a utilizar.
Para ello hacemos uso de la variable de entorno classpath, la cual puede ser establecida gráficamente si estamos en Windows (MiPC, botón derecho, propiedades) o bien por línea de comandos de la forma (versión Windows):
1 javac –classpath c:\java Principal.java
Siendo 'c:\java' el directorio donde nuestra clase (Principal.java) iría a buscar las clases que utiliza.


  • Para poder ver los valores de las variables vamos a definir un método para cada una.
Un método es un conjunto de instrucciones (bloque) identificado por un nombre (nombre del método) el cual puede ser llamado desde cualquier punto del programa, poniendo su nombre.
En ese momento, la secuencia de ejecución del programa cambia, deja de ir secuencialmente y 'salta' al bloque de instrucciones que conforman el método y continúa su ejecución de forma secuencial.
Cuando acaba de ejecutarse el método, 'vuelve' y continúa ejecutando las instrucciones que se encuentran a continuación de la llamada del método.
Prog fund poo 5.jpg
  • La forma de definir un método es el siguiente:
1 [tipo de acceso][static] tipoDato_devuelta nombre_metodo (lista de parámetros)
2 {
3    instrucción 1;
4    instrucción 2;
5    ..............
6    instrucción n;
7 
8 }
  • Veremos más adelante los tipos de acceso así como el modificador 'static'.


  • Cuando declaramos un método tenemos que indicar:
  • Cabecera del método: Contiene el nombre del método, el tipo de dato que va a devolver, una serie de modificadores (como los modificadores de acceso), y opcionalmente una lista de parámetros (representan datos que vamos a enviar al procedimiento cuando lo llamemos).
  • Cuerpo del método: Conjunto de instrucciones que se encuentran entre { }, incluido declaración de variables, las cuales son locales al método (quiere decir que dichas variables sólo son 'visibles' (se puede acceder a ellas) dentro del método. Fuera de él no existen.


En nuestro ejemplo crearemos dos métodos de la forma siguiente:
1 public void impNombre() {    // imprime el nombre
2       System.out.println("O nome é:" + nome);
3 }
  • Ejercicio: Escribir el código del método impEdad.


  • Estos métodos se definirán dentro de la clase Europeo, ya que manejan información que hace referencia a esa clase.
Por lo tanto, el código de clase Europeo completo hasta ahora es el siguiente:
 1 public class Europeo {       // Comienza el código de la clase 
 2   String nombre;
 3   int edad;
 4 
 5    public void impNombre() {   // imprime el nombre 
 6     System.out.println("O nome é:" + nome);
 7    }
 8 
 9   public void impEdad() {    // imprime la idad
10      System.out.println("O nome é:" + idade);
11   }
12 
13 } // Termina el código de la clase


  • En este punto, tenemos que compilar la clase para obtener los bytescodes actualizado (Europeo.class) (en Netbeans ya lo hace automaticamente al ejecutar la clase Principal).
En la clase Principal deberíamos llamar a estos métodos desde los objetos. Recuerde que un objeto posee todo los atributos y métodos definidos de la clase a la que pertenece.
  • Ejercicio: Cómo llamar a un método desde el objeto para imprimir el nombre y la edad.


  • El código de la clase principal completa es el siguiente:
 1 public class Principal {
 2 
 3     public static void main(String arg[]) {
 4         Europeo europeo1 = new Europeo();
 5         Europeo europeo2 = new Europeo();
 6         Europeo europeo3 = new Europeo();
 7         
 8         
 9         europeo1.nombre = "Angel";
10         europeo1.edad = 20;
11         europeo2.nombre = "Pepe";
12         europeo2.edad = 15;
13         europeo3.nombre = "Jean";
14         europeo3.edad = 17;
15         
16         
17         europeo1.impNombre();
18         europeo1.impEdad();
19         europeo2.impNombre();
20         europeo2.impEdad();
21         europeo3.impNombre();
22         europeo3.impEdad();
23     }
24 }
Si ejecutamos la clase principal una vez compilada, la consola mostrará los datos de los 3 creados en Europa.


  • Todo lenguaje de POO, como Java, tiene 3 características principales:
  • Herencia
  • Polimorfismo
  • Encapsulación
  • Definiremos cada uno de ellos y continuaremos con el ejemplo anterior.
  • La primera característica es HERENCIA:
Podemos establecer una relación entre 2 clases de tal manera que una de ellas "herede" todo lo que tiene la otra.
La herencia significa que no tenemos que redefinir todo el código, por lo que es reutilizable.
Pueden heredar tanto métodos como variables.
Gráficamente, podría ser algo como esto:
Prog fund poo 6.jpg


  • Como podemos ver, creamos dos subclases de la clase Europeo.
Esto conduce tanto la clase Espanol como la Francés.
  • La clase Frances hereda los métodos y variables de la clase Europeo, es decir, es como si ya dentro de su código se escribieran las definiciones de los atributos y métodos de clase Europeo.
  • Más adelante veremos que no todo es heredado y que existen restricciones.
También se debe tener en cuenta que en Java no se permite la herencia múltiple, es decir, que una clase hereda al mismo tiempo de dos o más clases.
Gráficamente sería lo siguiente:
Prog fund poo 7.jpg
  • Desde el punto de vista de la clase Europeo, la clase Espanol es una subclase de la clase Europeo.
  • Desde el punto de vista de la clase Espanol, la clase Europeo es una superclase de la clase de Espanol.


  • ¿ Cómo Java puede indicar que una clase es una subclase de otra ?
A través de la palabra clave extends.
  • En nuestro caso, supongamos que queremos almacenar la información referida al NIF (en el caso español) y al LIT (en el

caso francés).

También queremos tener los métodos que imprimen esta información, de nombres impNif e ImpLit.
  • Esta información pertenece a la clase Espanol y a la clase Frances, no pertenece a la clase Europeo.
Es por eso que deberíamos definir una clase con todo lo que la clase Europeo tenía más sus propios atributos.
En lugar de eso, crearemos dos subclases: Espanol y Frances que son subclases de la clase Europeo.
Por lo tanto, crearemos dos archivos más, uno para la clase de Espanol y el otro para la clase de Frances.
  • El nombre de archivo Espanol.java tendría lo siguiente:
1 public class Espanol extends Europeo {
2 
3     String nif;
4 
5     public void impNif() {
6         System.out.println("Nif:" + nif);
7     }
8 }


  • Ejercicio: Hacer el código de la clase Francés.




Solución:
1 public class Frances extends Europeo{
2 
3     String lit;
4 
5     public void impLit() {
6         System.out.println("Lit:" + lit);
7     }
8     
9 }


  • Ejercicio: Compilar as dúas clases no mesmo ficheiro físico. Que nome debe ter ? Cantas clases públicas hai

dentro do ficheiro ?


  • Ahora debemos modificar la clase Principal, ya que tenemos más información que se debe ajustar a la situacion:
Prog fund poo 8.jpg


  • Resulta que europeo1 y europeo2 son españoles, por lo tanto, deben ser objetos de la clase de Espanol, mientras que europeo3 es francés, por lo que debe ser un objeto de la clase de Frances.
Los cambios en la clase Principal son los siguientes:
  • Dos de los objetos se convierten en objetos de la clase de Espanol y uno en un objeto de la clase de Frances:
Espanol europeo1 = new Espanol();
Espanol europeo2 = new Espanol();
Frances europeo3 = new Frances();
  • El resto del código se mantiene.
  • Ejercicio: ¿ Por qué el objeto europeo1 puede utilizar los métodos y variables de la clase Europeo ?





  • Solución: Porque la clase a la que pertenece (Espanol) se define como una subclase de la clase Europeo y por lo tanto hereda todos los métodos y atributos de la clase Europeo.
  • Ejercicio: Los nuevos objetos tienen atributos propios (Nif y Lit)
Asigna un valor e mándalos imprimir.




  • Solución:
 1 public class Principal {
 2 
 3     public static void main(String arg[]) {
 4         Espanol europeo1 = new Espanol();
 5         Espanol europeo2 = new Espanol();
 6         Frances europeo3 = new Frances();
 7         
 8         
 9         europeo1.nombre = "Angel";
10         europeo1.edad = 20;
11         europeo2.nombre = "Pepe";
12         europeo2.edad = 15;
13         europeo3.nombre = "Jean";
14         europeo3.edad = 17;
15         
16         
17         europeo1.impNombre();
18         europeo1.impEdad();
19         europeo2.impNombre();
20         europeo2.impEdad();
21         europeo3.impNombre();
22         europeo3.impEdad();
23         
24         europeo1.nif="1111111A";
25         europeo2.nif="2222222A";
26         europeo3.lit="XA1111";
27         
28         europeo1.impNif();
29         europeo2.impNif();
30         europeo3.impLit();
31 
32         
33     }
34 }


  • Como podemos ver, el objeto europeo3 no puede llamar al método impNif, ya que este es un método de clase Espanol.
europeo3 es un objeto de la clase de Frances, por lo que tiene los atributos y métodos de la clase de Frances, además de los atributos y métodos de la clase Europeo ya que la clase Frances es una subclase de la clase Europeo.
  • La herencia no tiene que limitarse a un solo nivel, y así podemos tener otra subclase que sea Gallego y que tenga el atributo nifGalego y un método para imprimirlo impNifGalego().
Prog fund poo 9.jpg


Para implementar esta solución, debemos crear otra clase del nombre Gallego dentro de un archivo físico del nombre Gallego.java y que 'extienda' de la clase Espanol.

1 public class Gallego extends Espanol {
2 
3     String nifGallego;
4 
5     public void impNifGallego() {
6         System.out.println("Nif galego:" + nifGallego);
7     }
8 
9 }

Nota: Dependiendo de donde tengáis las clases, puede ser necesario el uso de la instrucción import. Si están en el mismo paquete no es necesario.


  • Partimos del hecho de que europeo2 es gallego y, por lo tanto, tiene un valor nif_galego "GA111111", por lo que debemos modificar la clase principal:
1 .....
2 .....
3 Gallego europeo2 = new Gallego();
4 ....
5 europeo2.nifGallego = "GA11111";
6 europeo2.impNifGallego ();
  • En este caso, europeo2 es un objeto de la clase Gallego, por lo que tiene las variables y métodos de la clase a la que pertenece, pero además esta clase es una subclase de la clase de Espanol, por lo que hereda todas las variables y métodos de esta clase, que a su vez es una subclase de la clase Europeo por lo que también hereda las variables e métodos de esta clase.



  • La segunda características de la POO es el POLIMORFISMO.
Esta característica hace referencia a la posibilidad de utilizar métodos definidos tanto en la superclase como en la subclases incluso si tienen el mismo nombre y argumentos.
  • Un ejemplo:
Supongamos que tenemos un método de nombre para impMaximosIngresos, que imprime los ingresos máximos que un europeo debe tener para hacer una declaración de hacienda.
Estos ingresos se almacenarán en una variable do nombre maximosIngresos, con un valor de 12048 euros.
  • Ejercicio: implementar la solución.






  • Solución: Debemos de declarar la variable maximosIngresos en la clase Europeo.
1 short maximosIngresos = 12048;
Observa cómo se inicializa esta variable, de modo que al crear un objeto esa clase tendrá dicho valor de forma predeterminada.
Si no lo hacemos así, debemos de dar un valor en la clase principal de la forma: europeo1.maximosIngresos = 12048;


Debemos de definir el método que imprime los ingresos máximos en la clase Europeo:
1 public void impMaximosIngresos() { // Imprime ingresos máximos
2    System.out.println ("Ingresos máximos son" + maximosIngresos + "euros");
3 }
y debemos modificar la clase Principal para imprimir esta variable:
Por ejemplo: europeo1.impMaximosIngresos ();


  • Sin embargo, queremos que imprima los ingresos máximos en pesetas para aquellos objetos que pertenecen a la clase Espanol o la clase Gallego.
¿Cómo podemos resolverlo? De dos maneras:
  • Declarando un nuevo método en la clase de Espanol que imprima el ingreso máximo en pesetas dando otro nombre que no sea el de la superclase, por ejemplo, impMaximosIngresosPesetas.
  • Declarar el método en la clase de Espanol, con el mismo nombre, pero imprimiendo la cantidad en pesetas.


  • La opción b) es lo que se conoce como polimorfismo.
En nuestro ejemplo, declararemos el siguiente método en clase Espanol:
1 @Override
2 public void impMaximosIngresos() {  // imprime el ingreso máximo en pesetas 
3     System.out.println ("Los ingresos máximos son" + maximosIngresos*166 + " pesetas");
4 }
Nota: El valor 166 tendría que estar definido en una constante.


Si ahora cambiamos la clase Principal para imprimir el ingreso máximo de los 3 objetos (personas):
1 europeo1.impMaximosIngresos();
2 europeo2.impMaximosIngresos();
3 europeo3.impMaximosIngresos();
Veremos que resulta que europeo1 y europeo2 imprimen el ingreso máximo en pesetas.
El objeto europeo3 imprime en euros, ya que el método lo ha heredado de la clase Europeo.
  • Su aplicación práctica la podríamos ver en el siguiente ejemplo.
Supongamos que necesitamos un método que imprima los ingresos máximos de los objetos que le vamos a pasar en forma de parámetros.
Dichos objetos podrán ser de la clase Frances, Espanol o Gallego.
La definición del método sería la siguiente:
1 public static void tratarObjetos(Europeo europeo) {
2 
3    europeo.impMaximosIngresos();
4 }
Como vemos, espera recibir un objeto de la clase Europeo. De esta forma podemos enviarle objetos de la clase Frances, Espanol o Gallego, ya que pertenecen a la Europeo.
Cuando el objeto 'europeo' llame al método 'impMaximosIngresos()' lo hará en función de la clase a la que pertenezca el objeto, de tal forma que si el objeto que enviamos pertenece a la clase Espanol. llamará al método que imprime el importe máximo en pesetas, y si enviamos un objeto que pertenezca a la clase Frances, llamará al método que imprima en Euros.
Si no lo hicierámos así, tendríamos que definir un método para imprimir objetos de la clase Espanol, otro para la clase Francés,...



  • Por lo tanto, para que haya polimorfismo, es necesario definir métodos en clases diferentes relacionadas con la herencia y deben de tener:
  • El mismo nombre
  • Los mismos parámetros (tipo y número)
  • El mismo tipo de dato de retorno
  • Los modificadores de acceso solo pueden ser iguales o menos restrictivos (indicado en la imagen siguiente).
Prog fund poo 10.jpg


  • El polimofismo implica que un objeto va a ejecutar un método en función de la clase a la que pertenece.




  • La última característica es la ENCAPSULACIÓN: los bloques compuestos en Java están delimitados por dos llaves ({}).
Las variables de Java solo son válidas desde el punto donde se declaran hasta el final del bloque donde están declaradas.
Es posible tener múltiples niveles de bloques anidados, y cada uno puede contener sus propias variables locales.
Sin embargo, no se puede declarar una variable con el mismo nombre que una de ámbito más exterior.
Por ejemplo:
Prog fund poo 11.jpg


  • Relacionados con la encapsulación están los modificadores de acceso, que modifican la visibilidad de las variables, clases y métodos (es decir, si se puede acceder al valor de una variable).
  • Se puede acceder a un método, clase o variable definida como public desde cualquier lugar.
  • Los métodos y variables:
  • private: solo se acceden desde los métodos de la propia clase, no son heredados por las subclases y no son accesible desde ellos.
  • protected: son visibles dentro de la clase, las subclases y las otras clases definidas dentro del mismo paquete (package).
Un paquete (package) es un grupo de clases relacionadas que se encuentran en el mismo archivo o en archivos diferentes, pero dentro del mismo directorio físico.
Todas las variables y métodos no privados se pueden ver desde todas las clases que pertenezcan al mismo paquete.
Más adelante ampliaremos la información sobre paquetes, cómo hacer uno y qué sirven ...
  • El siguiente cuadro es un resumen del anterior:
Prog fund poo 12.jpg
Nota: Una x indica que puede usar el método / variable declarado con ese modificador.


  • Profundizando un poco más en los conceptos diremos que un miembro (objeto, método, atributo...) privado es accesible solo para la clase en que se define
Este acceso se usa para declarar miembros que solo deberían ser utilizados por la clase.
Esto incluye a los objetos de estas clases que puedan ser utilizados por otras pero que si no fueran privados, podrían modificar los valores de sus atributos y dejar al objeto en un estado 'inconsistente'.
Por ejemplo:
Prog fund poo 13.jpg


  • Si tratamos de compilar la clase Beta, diremos que el atributo (variable) soyPrivado no es accesible.
Para poder modificar o leer el valor de la variable soyPrivado, necesitaríamos implementar dos métodos, uno que nos devuelva el valor y otro que le asignase un valor enviado como parámetro.
¿Cuál es la ventaja de esto? Que controlamos los valores que queremos asignar a la variable y, por lo tanto, hacemos que nuestra clase sea más robusta, es decir, que sea más difícil que falle.


  • Por ejemplo:
Prog fund poo 14.jpg
  • Ahora la temperatura (variable temp) tendrá el valor de 10 que asignaremos previamente.
Como podemos ver, el método asignarValor controla que nunca pasamos un número negativo y si lo pasamos por error asignará un valor predeterminado (valor 0)
Aunque la variable se declara como privada, los métodos 'asignarValor' y 'devolverValor' son públicos y van poder se llamados desde la otra clase a través del objeto 'a'.



  • Continuemos con nuestro ejemplo:
Supongamos que los españoles necesitan un método que informe cuánto debe pagar a hacienda por la cantidad de dinero ganado.
Por lo tanto, declararemos un método de nombre, pagarHacienda con un parámetro de entrada que nos informará de la cantidad ganada.
Como es un método que solo afecta a los españoles, lo declararemos en la clase de español y no en otro. Este método devolverá el dinero a pagar.
  • El proceso de este método es el siguiente:
  • Si la cantidad es > 1000, el importe a pagar se calcula de la siguiente manera:
Cantidad / GC_COEFICIENTE_1
  • Si la cantidad es <= 1000, entonces el importe a pagar se calcula de la siguiente manera:
Cantidad / GC_COEFICIENTE_2
GC_COEFICIENTE_1 valor constante: 10.12
GC_COEFICIENTE_1 valor constante: 11.33
  • Recuerda: Para crear una constante en Java, el modificador final debe preceder a la declaración y por convenio el nombre debe ir con letras mayúsculas y si tiene varias palabras, separadas por guión bajo.
Ejemplo: final int CONSTANTE = 10;



  • Ejercicio: implementar este método.
 1 public class Espanol extends Europeo {
 2     String nif;
 3     final float GC_COEFICIENTE_1 = 10.12f;
 4     final float GC_COEFICIENTE_2 = 11.33f;
 5     
 6     public double cantidadPagar(int cantidade) {
 7         if (cantidade < 1000) {
 8             return (cantidade / GC_COEFICIENTE_1);
 9         } else {
10             return (cantidade / GC_COEFICIENTE_2);
11         }
12     }
13     
14     public void impNif() {
15         System.out.println("Nif:" + nif);
16     }
17 
18     @Override
19     public void impMaximosIngresos() {  // imprime el ingreso máximo en pesetas 
20         System.out.println("Los ingresos máximos son" + maximosIngresos * 166 + " pesetas");
21     }
22 }


  • Pregunta: ¿ Qué problema tiene este método si creamos una instancia (objeto) de la clase de Gallego ?





  • Solución: Ese objeto heredará el método por lo cual podría llamarlo de la forma:
Gallego gallego1 = new Gallego();
System.out.println("Cantidad a pagar por 1000:" + gallego1.cantidadPagar(1000));


Y esto no queremos que suceda, ya que la clase Gallego no debería 'heredar' este método, solo los españoles que no son gallegos.
¿ Cómo resolver el problema ?: Declarar este método como privado. Entonces no serás heredado por las subclases y por lo tanto no podría llamarse desde la clase Gallego.
Pero al implementar esta solución encontramos el problema de que ni el método es visible para el objeto de la clase de Espanol.
Por lo tanto, la solución sería definirlo en la clase de Gallego, pero no devolverá el valor.
Es decir, en la clase de Espanol:
1 public double cantidadPagar(int cantidad) {
2    // CÓDIGO
3 }

y en la clase gallega:

1 public double cantidadPagar(int cantidad) {
2 }
Nota: Todos estos conceptos se usan nuevamente en el ejercicio 'Un programador novato'.


Organización de las clases

  • Jeráquica: Todas las clases provienen de la clase Object. La clase Object se encuentra en parte más alta del árbol de herencia en el entorno de desarrollo de Java.
Todas las clases del sistema Java son descendientes (directos o indirectos) de la clase Object. Esta clase define los estados y comportamientos básicos que deben tener todos los objetos, como la capacidad de comparar

un objeto con otro, de convertirse en cadenas, de devolver la clase a la que pertenece un objeto,...

  • Física: Cada paquete en Java hace referencia a las clases que se encuentran en un mismo directorio. Los paquetes son grupos relacionados de clases e interfaces y proporcionan un mecanismo para manejar un gran número de clases e interfaces y evitar conflictos de nombres. Además de los paquetes que proporciona Java, puedes crear tus propios paquetes y guardar en ellos tus propias clases e interfaces, utilizando la sentencia 'package'.


  • Supongamos que se está implementando un grupo de clases que representan una colección de objetos gráficos como círculos, rectángulos, líneas y puntos.
Podrás empaquetarlas en un paquete, por ejemplo, 'gráficos' y entregar el paquete a otros programadores (junto con la documentación de referencia).
  • De esta manera, otros programadores pueden determinar fácilmente cuales son tu grupo de clases, como utilizarlas, y cómo relacionarlos entre sí y con otras clases y paquetes. Los nombres de las clases no tienen conflictos con nombres de clases en otros paquetes porque las clases y las interfaces dentro de un paquete son referenciadas dentro de su paquete (técnicamente un paquete crea un nuevo espacio de nombres).

Un paquete se declara usando la sentencia 'package':

Prog fund poo 15.jpg
  • La primera línea del código anterior crea un paquete llamado graphics. Todas las clases e interfaces definidas en el archivo que contiene esta sentencia son miembros del paquete.
Por lo tanto, Draggable, Circle y Rectangle son miembros del paquete graphics.


  • Los archivos .class generados por el compilador al compilar el archivo anterior que contiene la definición de las clases Draggable, Circle y Rectangle deben ubicarse en un directorio llamado 'graphics' en algún lugar de la ruta CLASSPATH.
  • CLASSPATH es una lista de directorios que indica a Java donde se encuentran las clases e interfaces compilados. Cuando busca una clase, el intérprete de Java busca el directorio actual y en su CLASSPATH un directorio cuyo nombre coincida con el nombre del paquete del que la clase es miembro.
Los archivos .class para todas las clases y las interfaces definidas en un paquete deben estar en ese directorio del paquete.
Los nombres de los paquetes pueden contener subpaquetes (paquetes dentro de paquetes) (separados por punto). De hecho, los nombres de los paquetes Java tienen varios componentes: java.util, java.lang, etc ...
Cada componente del nombre del paquete representa un directorio en el sistema de archivos. Por lo tanto, los archivos .class de java.util están en un directorio llamado 'util' dentro de otro directorio llamado 'java' en algún lugar en CLASSPATH.
  • Para usar las clases en un paquete, utilizamos la importación antes de la definición de la clase.
Veámoslo en el siguiente ejemplo:
"Hmm", dice el programador novato, "tengo un problema. El coordinador del equipo de diseño me dijo que usaría la clase Calendar para ver la fecha y hora actual en mi aplicación, pero Java no parece entender la clase Calendar,
Me informa de un error cada vez que trato de usarla...".
Prog fund poo 16.jpg


  • "Esto se debe a que la clase 'Calendar' es parte del paquete de utilidades de Java y tienes que importar ese paquete antes de que pueda usarlo ".
"¿Importarlo?", Pregunte al programador.
  • Las clases que creó Sun se almacenan en bibliotecas de clase llamadas "paquetes". Para que una clase de un paquete esté disponible y pueda ser utilizada en otra clase, se debe importar el paquete, lo que significa que el compilador localizará ese paquete.
Por defecto, solo las clases básicas de Java están disponibles, aquellas que se encuentran en el paquete java.lang.
El compilador importa automáticamente el paquete java.lang, pero para usar el resto de las clases que vienen con Java tendrás que importarlas con la sentencia import.
1 import [paquete [.packet2 ...].]nombre de clase;
Para separar los diferentes subpaquetes (ya que podemos crear clases en un paquete que se encuentren dentro de de otro paquete) hay que colocar un punto ('.') entre el paquete y los subpaquetes.

Los paquetes de Java estándares se almacenan en un paquete grande llamado java, por lo que el paquete de utilidad se llama realmente java.util (hay otros paquetes grandes disponibles, por ejemplo, el paquete swing se almacena en el paquete java.swing).


  • En el ejemplo anterio de la clase Calendar, tendríamos que escribir el siguiente código:
 1 package POO;
 2 
 3 import java.util.Calendar;
 4 
 5 
 6 public class Principal {
 7 
 8     
 9     public static void main(String arg[]) {
10 
11         System.out.printf("Fecha actual %s",java.util.Calendar.getInstance().getTime());
12     }
13 
14 
15 }


  • Si quisiéramos 'importar' todas las clases de un determinado paquete, pondríamos '*' de la forma: import java.util.*;
Normalmente no deberíamos hacer uso de esta opción, ya que, aunque a nivel de rendimiento no supone ninguna diferencia, si que da problemas de claridad y problemas con clases que tengan el mismo nombre y que se encuentren en diferentes paquetes.
  • De claridad ya que no sabemos de que paquete proviene una clase que estemos utilizando en nuestro programa (podríamos tener varios import con *).
  • De 'choque' entre clases que se puedan llamar igual pero que estén en diferentes paquetes.
Por ejemplo:
java.lang.reflect.Array
java.sql.Array


  • En caso de no utilizar la sentencia 'import' podríamos utilizar la clase, pero tendríamos que referenciarla con su nombre completo.
En el ejemplo anterior: System.out.printf("Fecha actual %s",java.util.Calendar.getInstance().getTime());






-- Ángel D. Fernández González -- (2017).