02 julio, 2020

9. Herencia y polimorfismo: Sobre-escritura, clases y métodos abstractos, relación tiene-un


LOGRO DE LA UNIDAD DE APRENDIZAJE


Al término de la unidad, ustedes aplicarán el concepto de herencia y polimorfismo, la relación de generalización/especialización entre clases, se empleará las técnicas de casting y clases abstractas en casos prácticos.


TEMARIO


· Sobreescritura de métodos

· Clases y métodos abstractos

· Relación tiene-un

· Ejercicios + Link


ACTIVIDADES PROPUESTAS


· Ustedes emplean la sobreescritura de métodos

· Ustedes emplean clases y métodos abstractos

· Ustedes emplean la Herencia (relación tiene-un)


1) Sobreescritura de métodos


En una jerarquía de clases, cuando un método de una subclase tiene el mismo nombre, los mismos parámetros y el mismo tipo de retorno que un método de su superclase, se dice que el método de la subclase sobrescribe al método de la superclase.  Cuando se llama a un método sobrescrito dentro de una subclase, siempre se refiere a la versión del método definida en la subclase. La versión del método definida por la superclase queda oculta.


Uso de super para acceder a una variable oculta o a un método sobrescrito


Si desde la subclase se quiere acceder a una variable oculta de la superclase o a un método sobrescrito de la superclase, se usa la palabra super de la siguiente forma:


super.nombreDeLaVariableOculta

super.nombreDelMetodoSobreescrito (lista de argumentos)


Ejemplo 1


// Superclase
package semana12;
public class A {
   //Atributos
   public int i, j;
   //Constructor
   public A (int pi, int pj) {
      i = pi;
      j = pj;
   }
   //Método
   public int suma() {
      return i + j;
   }
}
// Subclase
package semana12;
public class B extends A {
   //Atributo
   public int k;
   //Constructor
   public B (int pi, int pj, int pk) {
      super(pi,pj);
      k = pk;
   }
   //Método
   public int suma() {
      return super.suma() + k;
   }
}
// Ejemplo de uso
import semana12.*;
...
...
void procesar(){
   A obj1 = new A(2,4);
   B obj2 = new B(1,3,5);
   imprimir(obj1.i + " + " + obj1.j + " = " + obj1.suma());
   imprimir(obj2.i + " + " + obj2.j + " + " + obj2.k + " = " +
   obj2.suma());
}


2) Clases y métodos abstractos 


Una clase abstracta es una clase que no se puede instanciar, se usa únicamente para crear subclases. 


Un método es abstracto cuando no tiene implementación y solamente se define con el objetivo de obligar a que en cada subclase que deriva de la clase abstracta se realice la correspondiente implementación, es decir en las subclases se va a sobre-escribir dicho método. En Java, tanto la clase como el método abstracto se etiqueta con la palabra reservada abstract. Sí se tiene en una clase por lo menos un método abstracto, entonces, la clase tiene que ser abstracta, sino el compilador mostrará un mensaje de error.





Figura es una clase abstracta porque no tiene sentido calcular su área, pero sí la de un cuadrado o un círculo. Si una subclase de Figura no redefine o sobre-escribe area(), deberá declararse también como clase abstracta.


Ejemplo 2


Código de la clase Figura:


package padre;
public abstract class Figura {
   protected int x;
   protected int y;
   public Figura(int x, int y) {
      this.x = x;
      this.y = y;
   }
   public String ubicacion(){
      return x+","+y;
   }
   public abstract double area();
}


Código de la clase Cuadrado:


package hijo;
import padre.Figura;
public class Cuadrado extends Figura {
   private double lado;
   public Cuadrado(int x, int y, double lado) {
      super(x, y);
      this.lado = lado;
   }
   //Sobre-escritura
   public double area() {
      return lado*lado;
   }
}


Código de la clase Circulo:


package hijo;
import padre.Figura;
public class Circulo extends Figura {
   private double radio;
   public Circulo(int x, int y, double radio) {
      super(x, y);
      this.radio=radio;
   }
   //Sobre-escritura
   public double area() {
      return Math.PI*radio*radio;
   }
}


Código de la clase Principal:


import hijo.*;
...
...
void procesar(){
   Cuadrado obj1=new Cuadrado(100,20,12);
   imprimir("Ubicación del cuadrado:"+obj1.ubicacion());
   imprimir("Area del cuadrado:"+obj1.area());
   Circulo obj2=new Circulo(300,200,20);
   imprimir("Ubicación del círculo:"+obj2.ubicacion());
   imprimir("Area del círculo:"+obj2.area());
}


Ejemplo 3 


Implemente la clase abstracta Vehiculo en el paquete padre que contenga el atributo capacidad del vehículo y un método abstracto caracteristicas() que se sobrescribirá en las subclases Carro y Avión. Por último, cree la clase Principal que contiene el actionPerformed() para crear los objetos de tipo Carro y Avión e imprima las características de dichos objetos.


Código de la clase Vehivulo:


// Superclase
package padre;

public abstract class Vehiculo {
 protected int capacidad;

 public Vehiculo(int capacidad) {
  this.capacidad = capacidad;
 }

 public abstract String caracteristicas();
}


Código de la clase Carro:


// Subclase
package hijo;

import padre.Vehiculo;

public class Carro extends Vehiculo {
 public Carro(int cap) {
  super(cap);
 }

 // Sobre-escritura
 public String caracteristicas() {
  return "Tengo una capacidad de " + capacidad + " pasajeros \n"
    + "Tengo 4 ruedas y una buena velocidad \n"
    + "pero no puedo volar";
 }
}


Código de la clase Avion

// Subclase
package hijo;

import padre.Vehiculo;

public class Avion extends Vehiculo {
 public Avion(int cap) {
  super(cap);
 }

 // Sobre-escritura
 public String caracteristicas() {
  return "Tengo una capacidad de " + capacidad + " pasajeros \n"
    + "Puedo volar, tengo una velocidad enorme \n"
    + "pero consumo mucho combustible";
 }
}


Código de la clase Principal:


// Ejemplo de uso – Clase Principal
import hijo.*;
...
...
void procesar(){
   Carro obj1 = new Carro(6);
   imprimir("Objeto Carro:");
   imprimir(obj1.caracteristicas());
   Avion obj2 = new Avion(300);
   imprimir("\nObjeto Avión:");
   imprimir(obj2.caracteristicas());
}


3) Relación tiene-un 


La relación tiene-un consiste en que la clase A tenga una referencia a un objeto de la clase B por ejemplo:


package semana12;
public class A {
   //Atributo privado
   private B obj;
}


De tal forma que, a través de la referencia obj, se puede acceder a los miembros de la clase B. 


Ejemplo 4


Diseñe un programa que, a la pulsación del botón Procesar, permita abrir la cuenta de un cliente. Para ello, considere que la cuenta tiene los siguientes datos: número de la cuenta, saldo de la cuenta, fecha de apertura (fecha del sistema en el formato: dd/mm/aaaa) y titular de la cuenta. El titular de la cuenta es un cliente que tiene los siguientes datos: código de cliente, nombre, apellidos y teléfono.


Código de la clase Cuenta:


package semana12;

public class Cuenta {
 // Atributos privados
 private int nro;
 private Cliente titular;
 private double saldo;
 private String fecApertura;
 private Fecha fec;

 // Constructor
 public Cuenta(int nro, Cliente titular, double saldo) {
  this.nro = nro;
  this.titular = titular;
  this.saldo = saldo;
  fec = new Fecha();
  fecApertura = fec.getFecha();
 }

 // Métodos de acceso: get
 public int getNro() {
  return nro;
 }

 public String getDatosTitular() {
  return "Codigo Cliente:" + titular.getCodigo() + "\n"
    + "Nombre Cliente:" + titular.getNombre() + "\n"
    + "Apellidos Cliente:" + titular.getApellidos() + "\n"
    + "Telefono Cliente:" + titular.getTelefono();
 }

 public double getSaldo() {
  return saldo;
 }

 public String getFechaApertura() {
  return fecApertura;
 }
}


Código de la clase Cliente


package semana12;

public class Cliente {
 // Atributos privados
 private int cod;
 private String nom, ape, telf;

 // Constructor
 public Cliente(int cod, String nom, String ape, String telf) {
  this.cod = cod;
  this.nom = nom;
  this.ape = ape;
  this.telf = telf;
 }

 // Métodos de acceso: get
 public int getCodigo() {
  return cod;
 }

 public String getNombre() {
  return nom;
 }

 public String getApellidos() {
  return ape;
 }

 public String getTelefono() {
  return telf;
 }
}


Código de la clase Fecha:


package semana12;

import java.util.*;

public class Fecha {
 // Atributos privados
 private int dd, mm, aa;
 private GregorianCalendar gc;

 // Constructor
 public Fecha() {
  gc = new GregorianCalendar();
  dd = gc.get(Calendar.DAY_OF_MONTH);
  mm = gc.get(Calendar.MONTH);
  aa = gc.get(Calendar.YEAR);
 }

 // Método
 public String getFecha() {
  return dd + "/" + (mm + 1) + "/" + aa;
 }
}


Código de la clase Principal


import semana12.*;
import semana12.*;
...
...
void procesar(){
   Cliente cli = new Cliente(100, "Rodolfo", "Garcia", "4451234");
   Cuenta cta = new Cuenta(925671, cli, 3500);
   listar(cta);
}

void listar(Cuenta x) {
   imprimir("Codigo de cuenta:" + x.getNro());
   imprimir("Titular de la cuenta:");
   imprimir(x.getDatosTitular());
   imprimir("Saldo de la cuenta:" + x.getSaldo());
   imprimir("Fecha de apertura de la cuenta:" + x.getFechaApertura());
}


Importante:  


La clase Cuenta tiene un objeto de tipo Cliente por lo que podemos acceder a los métodos de la clase Cliente con el método getDatosTitular().  

La clase Cuenta tiene un objeto de tipo Fecha por lo que podemos acceder al método getFecha() de la clase Fecha cuando hacemos fec.getFecha().  

La clase Fecha tiene un objeto de tipo GregorianCalendar por lo que podemos obtener el día, mes y año del sistema.


Ejemplo 5: 


Dada la clase Cuadrado que permite calcular el área de un cuadrado, se le pide diseñar una clase CuadradoRelleno que herede de la clase Cuadrado y que, además de permitir obtener el área del cuadrado, permita dibujar el cuadrado con un caracter de relleno especificado. Use, luego, la clase CuadradoRelleno para implementar el programa DibujoCuadrado que lea el lado y el caracter de relleno, y dibuje y muestre el área del cuadrado.



Código de la clase Cuadrado


public class Cuadrado {
 // Atributo
 private int lado;

 // Constructor
 public Cuadrado(int lado) {
  this.lado = lado;
 }

 // Fija el lado
 public void setLado(int lado) {
  this.lado = lado;
 }

 // Retorna el lado
 public int getLado() {
  return lado;
 }

 // Retorna el área
 public int area() {
  return lado * lado;
 }
}


Código de la clase CuadradoRelleno


public class CuadradoRelleno extends Cuadrado {
 private char car;
 private DibujoCuadrado gui;

 public CuadradoRelleno(int lado, char car, DibujoCuadrado gui) {
  super(lado);
  this.car = car;
  this.gui = gui;
 }

 public void dibujar() {
  for (int f = 1; f <= getLado(); f++) {
   for (int c = 1; c <= getLado(); c++)
    gui.txtS.append("" + car);
   gui.txtS.append("\n");
  }
 }
}


Programa DibujoCuadrado: Tenemos los métodos para obtener los datos de la GUI

//---------------------------------------------------------
int getLado(){
   return Integer.parseInt(txtLado.getText());
}
//---------------------------------------------------------
char getCaracter(){
   return txtCaracter.getText().charAt(0);
}


En el método Procesar se crea el objeto de tipo CuadradoRelleno y se llama a los métodos dibujar() y area()


void procesar(){
   int area;
   CuadradoRelleno c = new CuadradoRelleno
   (getLado(),getCaracter(),this);
   c.dibujar();
   area = c.area();
   txtS.append("\nEl Area es:"+area);
}


Descargar ejercicios

Descargar archivo 


Preguntas

¿Qué es la sobre-escritura de métodos y como usar el super?

¿Qué es una clase y método abstracto?

¿En qué consiste la relación tiene-un?

No hay comentarios, ¡cuéntame algo!

Me gustaría saber tu opinión. ¡Saludos!