Programación Orientada a Objetos con Java Rafael Rivera López II Elementos Básicos del Lenguaje Java Ingeniería en Sistemas Computacionales Agosto-Diciembre de 2004 Veracruz, Ver. Relación entre clases Las clases se pueden relacionar de tres formas: II.5 Herencia 1. Uso directo como una variable 2. Como atributo de otras clases (composición - agregación) 3. Con herencia Para ejemplificar estas relaciones se utiliza una clase llamada Punto Ejemplo de Clase: Punto public class Punto { public int getX() { return x; } protected int x,y; public Punto(int x, int y) { this.x = x; this.y = y; public int getY() { return y; } } II.5 public void mover(int x, int y) {} this.x = x; this.y = y; } Uso Directo public void desplazar(int dx, int dy) { x += dx; y += dy; } !" # Uso directo Uso directo Cuando se utiliza un objeto como variable local de un método, se está aplicando UsoPuntos la relación de uso directo main(String args[ ]) { Puntos p = new Puntos(10,10); ... } class UsoPuntos { public static void main(String[] args) { // ... Punto p; p = new Punto(14,27); System.out.println("("+p.getX()+","+p.getY()+")"); p.mover(100, 50); System.out.println("("+p.getX()+","+p.getY()+")"); p.desplazar(10, -5); System.out.println("("+p.getX()+","+p.getY()+")"); // ... } (14,27) } La clase no tiene atributos, pero usa directamente un objeto de la clase Point main (100,50) (110,45) Composición Se pueden utilizar objetos de una clase como atributos de otra clase. Esto se llama composición, ya que la nueva clase está compuesta de objetos de otras clases. II.5 Composición La composición utiliza la funcionalidad del código, no su forma. Composición Composición La relación entre dichas clases es tiene class Triangulo { private Punto vertice[] = new Punto[3]; public Triangulo (Punto p1, Punto p2, Punto p3) vertice[0] = new Punto(p1.getX(), p1.getY()); vertice[1] = new Punto(p2.getX(), p2.getY()); vertice[2] = new Punto(p3.getX(), p3.getY()); } Un triángulo tiene tres puntos { public void desplazar(int dx, int dy) { for(int i=0;i<3;i++) vertice[i].desplazar(dx,dy); } Un auto tiene cuatro ruedas y un motor public void mostrar() { for(int i=0;i<3;i++) System.out.println("Vértice "+(i+1)+ "("+vertice[i].getX()+","+vertice[i].getY()+")"); } } !" $ Composición Composición public class UsoTriangulos { public static void main(String [] args) { Triangulo triangulo = new Triangulo(new Punto(10,10), new Punto(20,40), new Punto(40,50)); El triangulo tiene tres vértices desplazar vertice[1] mover System.out.println("Triangulo creado"); triangulo.mostrar(); triangulo.desplazar(30,25); Triangulo creado System.out.println( "Triangulo desplazado"); Vértice 1(10,10) triangulo.mostrar(); Vértice 2(20,40) } x,y getX getX vertice[0] mover x,y ... vertice[2] getX Vértice 3(40,50) Triangulo desplazado Vértice 1(40,35) Vértice 2(50,65) Vértice 3(70,75) } mover x,y mostrar Triangulo Herencia Se puede utilizar una clase como base para crear otra clase II.5 Esto se llama herencia ya que una nueva clase obtiene atributos y comportamiento de otra. Herencia La herencia utiliza la forma de una clase para adecuarla a otra Herencia Herencia La herencia implementa la relación “es un” Un pixel es un punto con color Un administrador es un empleado con más funciones Punto x y Punto() mover() desplazar() getX() getY() !" Pixel setColor Pixel Usando herencia, se puede construir una jerarquía de tipos que expresa el problema en sus partes. La clase derivada tiene la misma interfaz de la clase base y podría adicionar atributos y métodos Color Pixel() setColor() getColor() mover x y color getColor ... desplazar getX getY % Herencia Herencia Al instanciar una clase derivada, este usa un constructor de la clase base La instancia de la clase base busca siempre un constructor sin parámetros en la clase base Se puede indicar que constructor de la clase base usar, utilizando la referencia super() public class Herencia1 { public static void main(String [] args){ Hijo1 hijo=new Hijo1(); System.out.println("El cabello es: "+hijo.cabello); hijo.nadar(); hijo.chatear(); } } Se usa un constructor por omisión y la instancia busca un constructor de la clase Padre que también es por omisión class Padre1 { int cabello; void nadar(){ System.out.println(“Se nadar”); Extends indica }; que Hijo1 } class Hijo1 extends Padre1 { void chatear(){ System.out.println(“Se chatear”); } } Herencia hereda de Padre1 Herencia public class Herencia2{ public static void main(String [] args){ Hijo2 hijo=new Hijo2(); System.out.println("El cabello es:"+hijo.cabello); hijo.nadar(); hijo.chatear(); } } class Padre2 { int cabello; public Padre2() { cabello=1; } void nadar(){ System.out.println("Se nadar"); }; } Se usa un constructor por omisión y la instancia busca un constructor de la clase Padre que es un constructor sin parámetros public class Herencia3{ public static void main(String [] args){ Hijo3 hijo=new Hijo3(3); ... } } class Padre3 { int cabello; public Padre3(int tipo) { cabello=tipo; } ... } Como la clase base no tiene constructor sin parámetros, la clase derivada lo debe llamar con la referencia super() class Hijo3 extends Padre3 { public Hijo3(int tipo){ super(tipo); } ... class Hijo2 extends Padre2 { void chatear(){ System.out.println("Se chatear"); } } } Ejemplo de Herencia import java.awt.*; Ejemplo de Herencia class UsoPixel { public class Pixel extends Punto { La clase Pixel hereda los atributos de Point public static void main(String[] args) { Pixel p = new Pixel(10,10,java.awt.Color.cyan); System.out.println( "(" + p.getX()+","+p.getY()+")"+p.getColor()); p.desplazar(40, 30); System.out.println( "(" + p.getX()+","+p.getY()+")"+p.getColor()); } private Color color; public Pixel (int x, int y, Color color) { super(x,y); this.color = color; } public Color getColor() { return color; } SALIDA: (10,10)java.awt.Color[r=0,g=255,b=255] } } (50,40)java.awt.Color[r=0,g=255,b=255] super(x,y) llama al constructor de la clase padre (point) !" El objeto p tiene los métodos de point & La clase Object Java define la clase java.lang.Object que se entiende como una super-clase de todas las clases. II.6 Si una clase no especifica de que clase se deriva, entonces se deriva de la clase Object. El modificador static Asocia al miembro (variable o método) con la clase más que con el objeto Los métodos declarados como static no actúan sobre un objeto particular Se puede escribir una clase que sea un conjunto de miembros estáticos, esta clase no define un nuevo objeto, sino que es una librería de utilierías que tienen relación entre ellas. Métodos estáticos Cuando se llama a un método estático, se debe indicar la clase a la que pertenece: double x = Math.sin(alpha); int c = Math.max(a,b); double y = Math.random(); El método main es static; es invocado por el sistema sin crear un objeto. Si un método estático llama a otro método estático de la misma clase se puede omitir el nombre de la clase. !" Modificador static Métodos estáticos public class Math { // Calcula en seno public static double sin(double x) { // ... } sin y log son métodos estáticos, no se asocian a ningún objeto // Calcula el logaritmo public static double log(double x) { // ... } ... } Variables estáticas Una variable que es declarada como estática es asociada con la clase, no con alguna instancia de ella. Las variables estáticas se conocen como variables de clase. Se considerarían como variables globales. ' Variables estáticas public class Billetes { private int cantidad; private int numeroSerie; private static int contadorBilletes; Variables estáticas La variable contadorBilletes es estática public Billetes(int cantidad) { this.cantidad = cantidad; contadorBilletes++; numeroSerie = contadorBilletes; } public int verNumeroSerie() { return numeroSerie; } En el Constructor ... se actualiza la variable estática que sirve como un contador global this y static No existe this para un miembro static. Puede llamar a un método static de la misma clase, sin un objeto. Puede referenciar a un miembro estático sin existir un objeto. Integer.parseInt(“123”); Calendar.SUNDAY !" public static void main(String[] args) { Billetes billetes[] = new Billetes[20]; for(int i=10;i<30;i++){ billetes[i-10] = new Billetes(10); System.out.println("El número de serie es :" + (billetes[i-10].verNumeroSerie())); } } } Cada billete tiene su número de serie único Miembros de clase y static Todos los métodos no estáticos tienen acceso a todos los datos de una clase. Los métodos estáticos de la clase tienen acceso solo a los datos estáticos. (