[código] Programación Orientada a Objetos: Polimorfismo (1)
En esta sección puedes descargar ejemplos de Polimorfismo (Programación Orientada a Objetos). Los ejemplos muestran la diferencia de clases abstractas (abstract) y clases concretas; además de presentar las interfaces, que es el “reemplazo” de la llamada “herencia múltiple” de C++. También presenta el concepto de las clases anidadas, las cuales utilizamos en este caso para el manejo de eventos de componentes de la GUI. Véase especialmente tres ejemplos prácticos de polimorfismo: un sistema de nóminas, una jerarquía de figuras encabezada por una clase abstract y una jerarquía de clases encabezada por una interfaz.
Asignación de referencias de superclase y subclase a la variable de tipo superclase y subclase
Este ejemplo contiene 3 clases; la primera de ellas es la clase Punto3:
// La declaración de la clase Punto representa un par de coordenadas x-y.
public class Punto3 {
private int x; // parte x de un par de coordenadas
private int y; // parte y de un par de coordenadas
// constructor sin argumentos
public Punto3()
{
// la llamada implícita al constructor de Object ocurre aquí
}
// constructor
public Punto3( int valorX, int valorY )
{
// la llamada implícita al constructor de Object ocurre aquí
x = valorX; // no hay necesidad de validación
y = valorY; // no hay necesidad de validación
}
// establecer x en el par de coordenadas
public void establecerX( int valorX )
{
x = valorX; // no hay necesidad de validación
}
// devolver x del par de coordenadas
public int obtenerX()
{
return x;
}
// establecer y en el par de coordenadas
public void establecerY( int valorY )
{
y = valorY; // no hay necesidad de validación
}
// devolver y del par de coordenadas
public int obtenerY()
{
return y;
}
// devolver la representación String del objeto Punto3
public String toString()
{
return "[" + obtenerX() + ", " + obtenerY() + "]";
}
} // fin de la clase Punto3
La segunda es la clase Circulo4:
// La clase Circulo4 hereda de Punto3 y accede a las variables x e y
// de Punto 3 mediante los métodos public de Punto3.
public class Circulo4 extends Punto3 {
private double radio; // El radio de Circulo4
// constructor sin argumentos
public Circulo4()
{
// la llamada implícita al constructor de Punto3 ocurre aquí
}
// constructor
public Circulo4( int valorX, int valorY, double valorRadio )
{
super( valorX, valorY ); // llama al constructor de Punto3 explícitamente
establecerRadio( valorRadio );
}
// establecer el radio
public void establecerRadio( double valorRadio )
{
radio = ( valorRadio < 0.0 ? 0.0 : valorRadio );
}
// devolver el radio
public double obtenerRadio()
{
return radio;
}
// calcular y devolver el diámetro
public double obtenerDiametro()
{
return 2 * obtenerRadio();
}
// calcular y devolver la circunferencia
public double obtenerCircunferencia()
{
return Math.PI * obtenerDiametro();
}
// calcular y devolver el área
public double obtenerArea()
{
return Math.PI * obtenerRadio() * obtenerRadio();
}
// devolver la representación String del objeto Circulo4
public String toString()
{
return "Centro = " + super.toString() + "; Radio = " + obtenerRadio();
}
} // fin de la clase Circulo4
Y la tercera es la clase PruebaRelacionJerarquia1:
// Asignación de referencias de superclases y subclases a variables tipo
// superclase y subclase.
import javax.swing.JOptionPane;
public class PruebaRelacionJerarquia1 {
public static void main( String[] args )
{
// asignar a la variable tipo superclase, la referencia a la superclase
Punto3 punto = new Punto3( 30, 50 );
// asignar a la referencia de la subclase, la variable tipo subclase
Circulo4 circulo = new Circulo4( 120, 89, 2.7 );
// invocar a toString en objeto de superclase usando variable de superclase
String salida = "Llamar a toString de Punto3 con la referencia a la" +
" superclase apuntando al objeto de la superclase: \n" + punto.toString();
// invocar a toString en objeto de subclase usando variable de subclase
salida += "\n\nLlamar a toString de Circulo4 con la referencia a la" +
" subclase apuntando al objeto de la subclase: \n" + circulo.toString();
// invocar a toString en objeto de subclase utilizando variable de superclase
Punto3 refPunto = circulo;
salida += "\n\nLlamar a toString de Circulo4 con la referencia a la" +
" superclase apuntando al objeto de la subclase: \n" + refPunto.toString();
JOptionPane.showMessageDialog( null, salida ); // mostrar la salida
System.exit( 0 );
} // fin de main
} // fin de la clase PruebaRelacionJerarquia1
Herencia de Interfaz y de implementación. Jerarquía Figura->Punto->Criculo->Cilindro
Este ejemplo contiene 5 clases; la primera de ellas es la clase Figura:
// Declaración de la superclase abstracta Figura.
public abstract class Figura extends Object
{
// devolver el área de la figura; 0.0 de manera predeterminada
public double obtenerArea()
{
return 0.0;
}
// devolver el volumen de la figura; 0.0 de manera predeterminada
public double obtenerVolumen()
{
return 0.0;
}
// método abstracto, sobrescrito por las subclases
public abstract String obtenerNombre();
} // fin de la clase abstracta Figura
La segunda es la clase Punto:
// Declaración de la clase Punto que hereda de Figura.
public class Punto extends Figura {
private int x; // parte x del par de coordenadas
private int y; // parte y del par de coordenadas
// constructor sin argumentos; valor predeterminado de 0 para x e y
public Punto()
{
// la llamada implícita al constructor de Object ocurre aquí
}
// constructor
public Punto( int valorX, int valorY )
{
// la llamada implícita al constructor de Object ocurre aquí
x = valorX; // no hay necesidad de validación
y = valorY; // no hay necesidad de validación
}
// establecer x en el par de coordenadas
public void establecerX( int valorX )
{
x = valorX; // no hay necesidad de validación
}
// devolver x del par de coordenadas
public int obtenerX()
{
return x;
}
// establecer y en el par de coordenadas
public void establecerY( int valorY )
{
y = valorY; // no hay necesidad de validación
}
// devolver y del par de coordenadas
public int obtenerY()
{
return y;
}
// sobrescribir el método abstracto obtenerNombre para devolver "Punto"
public String obtenerNombre()
{
return "Punto";
}
// sobrescribir a toString para devolver la representación String de Punto
public String toString()
{
return "[" + obtenerX() + ", " + obtenerY() + "]";
}
} // fin de la clase Punto
La tercera es la clase Circulo:
// La clase Circulo que hereda de Punto.
public class Circulo extends Punto {
private double radio; // radio del Circulo
// constructor sin argumentos; el valor predeterminado de radio es 0.0
public Circulo()
{
// la llamada implícita al constructor de Punto ocurre aquí
}
// constructor
public Circulo( int x, int y, double valorRadio )
{
super( x, y ); // llamar al constructor de Punto
establecerRadio( valorRadio );
}
// establecer el radio
public void establecerRadio( double valorRadio )
{
radio = ( valorRadio < 0.0 ? 0.0 : valorRadio );
}
// devolver el radio
public double obtenerRadio()
{
return radio;
}
// calcular y devolver el diámetro
public double obtenerDiametro()
{
return 2 * obtenerRadio();
}
// calcular y devolver la circunferencia
public double obtenerCircunferencia()
{
return Math.PI * obtenerDiametro();
}
// sobrescribir el método abstracto obtenerArea para devolver área del Circulo
public double obtenerArea()
{
return Math.PI * obtenerRadio() * obtenerRadio();
}
// sobrescribir el método abstracto obtenerNombre para devolver "Circulo"
public String obtenerNombre()
{
return "Circulo";
}
// sobrescribir toString para devolver la representación String de Circulo
public String toString()
{
return "Centro = " + super.toString() + "; Radio = " + obtenerRadio();
}
} // fin de la clase Circulo
La cuarta es la clase Cilindro:
// La clase Cilindro que hereda de Circulo.
public class Cilindro extends Circulo {
private double altura; // la altura del Cilindro
// constructor sin argumentos; el valor predeterminado de altura es 0.0
public Cilindro()
{
// la llamada implícita al constructor de Circulo ocurre aquí
}
// constructor
public Cilindro( int x, int y, double radio, double valorAltura )
{
super( x, y, radio ); // llamar al constructor de Circulo
establecerAltura( valorAltura );
}
// establecer la altura del Cilindro
public void establecerAltura( double valorAltura )
{
altura = ( valorAltura < 0.0 ? 0.0 : valorAltura );
}
// obtener la altura del Cilindro
public double obtenerAltura()
{
return altura;
}
// sobrescribir método abstracto obtenerArea para devolver area de Cilindro
public double obtenerArea()
{
return 2 * super.obtenerArea() + obtenerCircunferencia() * obtenerAltura();
}
// sobrescribir método abstracto obtenerVolumen para devolver valor del Cilindro
public double obtenerVolumen()
{
return super.obtenerArea() * obtenerAltura();
}
// sobrescribir método abstracto obtenerNombre para devolver "Cilindro"
public String obtenerNombre()
{
return "Cilindro";
}
// sobrescribir toString para devolver representación String del Cilindro
public String toString()
{
return super.toString() + "; Altura = " + obtenerAltura();
}
} // fin de la clase Cilindro
La quinta es la clase PruebaHerenciaAbstracta, que contiene el mértodo main:
// Controlador para la jerarquía figura, punto, circulo, cilindro.
import java.text.DecimalFormat;
import javax.swing.JOptionPane;
public class PruebaHerenciaAbstracta {
public static void main( String args[] )
{
// establecer el formato de número de punto flotante
DecimalFormat dosDigitos = new DecimalFormat( "0.00" );
// crear objetos Punto, Circulo y Cilindro
Punto punto = new Punto( 7, 11 );
Circulo circulo = new Circulo( 22, 8, 3.5 );
Cilindro cilindro = new Cilindro( 20, 30, 3.3, 10.75 );
// obtener nombre y representación de cadena de cada objeto
String salida = punto.obtenerNombre() + ": " + punto + "\n" +
circulo.obtenerNombre() + ": " + circulo + "\n" +
cilindro.obtenerNombre() + ": " + cilindro + "\n";
Figura arregloDeFiguras[] = new Figura[ 3 ]; // crear arreglo de Figuras
// apuntar arregloDeFiguras[ 0 ] al objeto de la subclase Punto
arregloDeFiguras[ 0 ] = punto;
// apuntar arregloDeFiguras[ 1 ] al objeto de la subclase Circulo
arregloDeFiguras[ 1 ] = circulo;
// apuntar arregloDeFiguras[ 2 ] al objeto de la subclase Cilindro
arregloDeFiguras[ 2 ] = cilindro;
// iterar a través de arregloDeFiguras para obtener nombre, representación
// de cadena, área y volumen para cada Figura en el arreglo
for ( int i = 0; i < arregloDeFiguras.length; i++ ) {
salida += "\n\n" + arregloDeFiguras[ i ].obtenerNombre() + ": " +
arregloDeFiguras[ i ].toString() + "\nArea = " +
dosDigitos.format( arregloDeFiguras[ i ].obtenerArea() ) +
"\nVolumen = " +
dosDigitos.format( arregloDeFiguras[ i ].obtenerVolumen() );
}
JOptionPane.showMessageDialog( null, salida ); // mostrar resultados
System.exit( 0 );
} // fin de main
} // fin de la clase PruebaHerenciaAbstracta
Utilización de clases internas para el manejo de eventos
este ejemplo posee 2 clases; la primera es la clase Tiempo:
// Declaración de la clase Tiempo con métodos establecer y obtener.
import java.text.DecimalFormat;
public class Tiempo
{
private int hora; // 0 - 23
private int minuto; // 0 - 59
private int segundo; // 0 - 59
// un objeto de formato para compartir en toString y aStringUniversal
private static DecimalFormat dosDigitos = new DecimalFormat( "00" );
// el constructor de Tiempo inicializa cada variable de instancia en cero;
// se asegura que cada objeto Tiempo inicie en un estado consistente
public Tiempo()
{
this( 0, 0, 0 ); // invocar al constructor de Tiempo con tres argumentos
}
// constructor de Tiempo: se proporciona hora; minuto y segundo con valor predeterminado de 0
public Tiempo( int h )
{
this( h, 0, 0 ); // invocar al constructor de Tiempo con tres argumentos
}
// constructor de Tiempo: se proporcionan hora y minuto, segundo con valor predeterminado de 0
public Tiempo( int h, int m )
{
this( h, m, 0 ); // invocar al constructor de Tiempo con tres argumentos
}
// constructor de Tiempo: se proporcionan hora, minuto y segundo
public Tiempo( int h, int m, int s )
{
establecerTiempo( h, m, s );
}
// constructor de Tiempo: se suministra otro objeto Tiempo3
public Tiempo( Tiempo tiempo )
{
// invocar al constructor de Tiempo con tres argumentos
this( tiempo.obtenerHora(), tiempo.obtenerMinuto(), tiempo.obtenerSegundo() );
}
// Métodos Establecer
// establecer un nuevo valor de tiempo, utilizando la hora universal; realizar
// comprobaciones de validez en los datos; establecer valores inválidos en cero
public void establecerTiempo( int h, int m, int s )
{
establecerHora( h ); // establecer la hora
establecerMinuto( m ); // establecer el minuto
establecerSegundo( s ); // establecer el segundo
}
// validar y establecer hora
public void establecerHora( int h )
{
hora = ( ( h >= 0 && h < 24 ) ? h : 0 );
}
// validar y establecer minuto
public void establecerMinuto( int m )
{
minuto = ( ( m >= 0 && m < 60 ) ? m : 0 );
}
// validar y establecer segundo
public void establecerSegundo( int s )
{
segundo = ( ( s >= 0 && s < 60 ) ? s : 0 );
}
// Métodos Obtener
// obtener valor de hora
public int obtenerHora()
{
return hora;
}
// obtener valor de minuto
public int obtenerMinuto()
{
return minuto;
}
// obtener valor de segundo
public int obtenerSegundo()
{
return segundo;
}
// convertir a String en formato de hora universal
public String aStringUniversal()
{
return dosDigitos.format( obtenerHora() ) + ":" +
dosDigitos.format( obtenerMinuto() ) + ":" +
dosDigitos.format( obtenerSegundo() );
}
// convertir a String en formato de hora estándar
public String toString()
{
return ( ( obtenerHora() == 12 || obtenerHora() == 0 ) ?
12 : obtenerHora() % 12 ) + ":" + dosDigitos.format( obtenerMinuto() ) +
":" + dosDigitos.format( obtenerSegundo() ) +
( obtenerHora() < 12 ? " AM" : " PM" );
}
} // fin de la clase Tiempo
Y la segunda es la clase VentanaPruebaTiempo, que contiene el método main:
// Declaraciones de clase interna utilizadas para crear manejadores de eventos.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class VentanaPruebaTiempo extends JFrame
{
private Tiempo tiempo;
private JLabel horaEtiqueta, minutoEtiqueta, segundoEtiqueta;
private JTextField horaCampo, minutoCampo, segundoCampo, pantallaCampo;
private JButton salirBoton;
// configurar GUI
public VentanaPruebaTiempo()
{
// llamar al constructor de JFrame para establecer cadena de barra de título
super( "Demostración de clase interna" );
tiempo = new Tiempo(); // crear objeto Tiempo
// usar método heredado getContentPane para obtener panel de contenido de la ventana
Container contenedor = getContentPane();
contenedor.setLayout( new FlowLayout() ); // cambiar esquema
// preparar horaEtiqueta y horaCampo
horaEtiqueta = new JLabel( "Ajuste hora" );
horaCampo = new JTextField( 10 );
contenedor.add( horaEtiqueta );
contenedor.add( horaCampo );
// preparar minutoEtiqueta y minutoCampo
minutoEtiqueta = new JLabel( "Ajuste minuto" );
minutoCampo = new JTextField( 10 );
contenedor.add( minutoEtiqueta );
contenedor.add( minutoCampo );
// preparar segundoEtiqueta y segundoCampo
segundoEtiqueta = new JLabel( "Ajuste segundo" );
segundoCampo = new JTextField( 10 );
contenedor.add( segundoEtiqueta );
contenedor.add( segundoCampo );
// establecer pantallaCampo
pantallaCampo = new JTextField( 30 );
pantallaCampo.setEditable( false );
contenedor.add( pantallaCampo );
// establecer salirBoton
salirBoton = new JButton( "Salir" );
contenedor.add( salirBoton );
// crear una instancia de la clase interna ActionEventHandler
ActionEventHandler manejador = new ActionEventHandler();
// registrar manejadores de eventos; el objeto referenciado por manejador
// es el ActionListener, el cual contiene el método actionPerformed
// que será llamado para manejar los eventos de acción generados por
// horaCampo, minutoCampo, segundoCampo y salirBoton
horaCampo.addActionListener( manejador );
minutoCampo.addActionListener( manejador );
segundoCampo.addActionListener( manejador );
salirBoton.addActionListener( manejador );
} // fin del constructor
// mostrar tiempo en pantallaCampo
public void mostrarTiempo()
{
pantallaCampo.setText( "La hora es: " + tiempo );
}
// iniciar aplicación: crear, ajustar tamaño y mostrar VentanaPruebaTiempo;
// cuando main termina, el programa continua ejecutándose ya que
// se muestra una ventana mediante las instrucciones en main
public static void main( String args[] )
{
VentanaPruebaTiempo ventana = new VentanaPruebaTiempo();
ventana.setSize( 400, 140 );
ventana.setVisible( true );
} // fin de main
// declaración de clase interna para manejar eventos JTextField y JButton
private class ActionEventHandler implements ActionListener {
// método para manejar eventos de acción
public void actionPerformed( ActionEvent evento )
{
// el usuario oprimió salirBoton
if ( evento.getSource() == salirBoton )
System.exit( 0 ); // terminar la aplicación
// el usuario oprimió tecla Intro en horaCampo
else if ( evento.getSource() == horaCampo ) {
tiempo.establecerHora( Integer.parseInt(
evento.getActionCommand() ) );
horaCampo.setText( "" );
}
// el usuario oprimió tecla Intro en minutoCampo
else if ( evento.getSource() == minutoCampo ) {
tiempo.establecerMinuto( Integer.parseInt(
evento.getActionCommand() ) );
minutoCampo.setText( "" );
}
// el usuario oprimió tecla Intro en segundoCampo
else if ( evento.getSource() == segundoCampo ) {
tiempo.establecerSegundo( Integer.parseInt(
evento.getActionCommand() ) );
segundoCampo.setText( "" );
}
mostrarTiempo(); // llamar a un método de la clase externa
} // fin del método actionPerformed
} // fin de la clase interna ActionEventHandler
} // fin de la clase VentanaPruebaTiempo
Utilización de clases internas anónimas para el manejo de eventos
este ejemplo posee 2 clases; la primera es la clase Tiempo (que es la misma del anterior ejemplo); y la segunda es la clase VentanaPruebaTiempo2, que contiene el método main:
// Demostración de los métodos establecer y obtener de la clase Tiempo
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class VentanaPruebaTiempo2 extends JFrame {
private Tiempo tiempo;
private JLabel horaEtiqueta, minutoEtiqueta, segundoEtiqueta;
private JTextField horaCampo, minutoCampo, segundoCampo, pantallaCampo;
// constructor
public VentanaPruebaTiempo2()
{
// llamar al constructor de JFrame para establecer cadena de barra de título
super( "Demostración de clase interna anónima" );
tiempo = new Tiempo(); // crear objeto Tiempo
crearGUI(); // configurar GUI
registrarManejadoresDeEventos(); // configurar el manejo de eventos
}
// crear componentes de GUI y adjuntarlos al panel de contenido
private void crearGUI()
{
Container contenedor = getContentPane();
contenedor.setLayout( new FlowLayout() );
horaEtiqueta = new JLabel( "Ajuste hora" );
horaCampo = new JTextField( 10 );
contenedor.add( horaEtiqueta );
contenedor.add( horaCampo );
minutoEtiqueta = new JLabel( "Ajuste minuto" );
minutoCampo = new JTextField( 10 );
contenedor.add( minutoEtiqueta );
contenedor.add( minutoCampo );
segundoEtiqueta = new JLabel( "Ajuste segundo" );
segundoCampo = new JTextField( 10 );
contenedor.add( segundoEtiqueta );
contenedor.add( segundoCampo );
pantallaCampo = new JTextField( 30 );
pantallaCampo.setEditable( false );
contenedor.add( pantallaCampo );
} // fin del método crearGUI
// registrar manejadores de eventos para horaCampo, minutoCampo y segundoCampo
private void registrarManejadoresDeEventos()
{
// registrar manejador de eventos para horaCampo
horaCampo.addActionListener(
new ActionListener() { // clase interna anónima
public void actionPerformed( ActionEvent evento )
{
tiempo.establecerHora( Integer.parseInt(
evento.getActionCommand() ) );
horaCampo.setText( "" );
mostrarTiempo();
}
} // fin de la clase interna anónima
); // fin de la llamada a addActionListener para horaCampo
// registrar manejador de eventos para minutoCampo
minutoCampo.addActionListener(
new ActionListener() { // clase interna anónima
public void actionPerformed( ActionEvent evento )
{
tiempo.establecerMinuto( Integer.parseInt(
evento.getActionCommand() ) );
minutoCampo.setText( "" );
mostrarTiempo();
}
} // fin de la clase interna anónima
); // fin de la llamada a addActionListener para minutoCampo
segundoCampo.addActionListener(
new ActionListener() { // clase interna anónima
public void actionPerformed( ActionEvent evento )
{
tiempo.establecerSegundo( Integer.parseInt(
evento.getActionCommand() ) );
segundoCampo.setText( "" );
mostrarTiempo();
}
} // fin de la clase interna anónima
); // fin de la llamada a addActionListener para segundoCampo
} // fin del método registrarManejadoresDeEventos
// mostrar tiempo en pantallaCampo
public void mostrarTiempo()
{
pantallaCampo.setText( "La hora es: " + tiempo );
}
// crear objeto VentanaPruebaTiempo2, registrarse para sus eventos de ventana
// y mostrarlo para empezar la ejecución de la aplicación
public static void main( String args[] )
{
VentanaPruebaTiempo2 ventana = new VentanaPruebaTiempo2();
// registrar componente de escucha para evento windowClosing
ventana.addWindowListener(
// clase interna anónima para evento windowClosing
new WindowAdapter() {
// terminar la aplicación cuando el usuario cierra la ventana
public void windowClosing( WindowEvent evento )
{
System.exit( 0 );
}
} // fin de la clase interna anónima
); // fin de la llamada a addWindowListener para ventana
ventana.setSize( 400, 120 );
ventana.setVisible( true );
} // fin de main
} // fin de la clase VentanaPruebaTiempo2
13 Comentarios | deja el tuyo





muy buenos ejemplos
Gracias, en realidad los ejemplos son muy ilsutrativos
Asuu q buenos ejercicios poco a poco se siente la dificultad
ta xvre los codigos weno me gustaria k me ayudes hacer un programa para una ferreteria me falta algunos detalles
grax broder por os codigos, ya que empiezo la carrera de ISC me son muy utiles espero sigan publicando mas codigos, GRAX carnal
lo que miro no es polimorfismo es herencia
pienso lo mismo que mario……
muy buenos ejemplos los analizaré para corroborar si realmente aplica polimorfismo o solo herencia
si yo opino lo mismo que trata de herencia aunque muy buenos ejemplos
GRACIAS SON MUY BUENOS EJEMPLOS
se ven muy buenos esos ejercicios,fata ejecutarlos nomas……
AMIGO QUE PACIENCIA TIENES PARA COPIAR LOS CODIGOS DEL LIBRO DEITEL Y DEITEL QUINTA EDICION.. SALUDOS