PDF de programación - Polimorfismo - Piensa en Java

Imágen de pdf Polimorfismo - Piensa en Java

Polimorfismo - Piensa en Javagráfica de visualizaciones

Publicado el 6 de Noviembre del 2020
965 visualizaciones desde el 6 de Noviembre del 2020
990,6 KB
32 paginas
Creado hace 19a (21/11/2004)
7: Polimorfismo

El polimorfismo es la tercera característica esencial de los lenguajes de progra-
mación orientados a objetos, después de la abstracción de datos y la herencia.

Proporciona otra dimensión de separación de la interfaz de la implementación, separa el qué del
cómo. El polimorfismo permite una organización de código y una legibilidad del mismo mejorada,
además de la creación de programas ampliables que pueden "crecer", no sólo durante la creación
original del proyecto sino también cuando se deseen añadir nuevas características.

La encapsulación crea nuevos tipos de datos mediante la combinación de características y compor-
tamientos. La ocultación de la implementación separa la interfaz de la implementación haciendo los
detalles privados. Este tipo de organización mecánica tiene bastante sentido para alguien con un
trasfondo procedural de programación. Pero el polimorfismo tiene que ver con la separación en tér-
minos de tipos. En el capítulo anterior se vio como la herencia permite el tratamiento de un objeto
como si fuera de sus propio tipo o del tipo base. Esta característica es crítica porque permite que va-
rios tipos (derivados de un mismo tipo base) sean tratados como si fueran uno sólo, y un único frag-
mento de código se puede ejecutar de igual forma en todos los tipos diferentes. La llamada a un mé-
todo polimórfico permite que un tipo exprese su distinción de otro tipo similar, puesto que ambos
se derivan del mismo tipo base. Esta distinción se expresa a través de diferencias en comporta-
miento de los métodos a los que se puede invocar a través de la clase base.

En este capítulo, se aprenderá lo relacionado con el polimorfismo (llamado también reubicación di-
námica, reubicación tardía o reubicación en tiempo de ejecución) partiendo de la base, con ejemplos
simples que prescinden de todo, menos del comportamiento polimórfico del programa.

De nuevo la conversión hacia arriba

En el Capítulo 6 se vio cómo un objeto puede usarse con su propio tipo o como un objeto de su tipo
base. Tomar una referencia a un objeto y tratarla como una referencia a su clase base se denomina
conversión hacia arriba, debido a la forma en que se dibujan los árboles de herencia, en los que la
clase base se coloca siempre en la parte superior.

También se vio que surge un problema, como se aprecia en:

/ / : c07:musica:Musica.java
/ / Herencia y conversión hacia arriba.

class Nota {

private int valor;
private Nota(int val) { valor = val; }
public static final Nota

-

DO MAYOR = new Nota(O),
DO SOSTENIDO = new Nota (1) ,

-

224

Piensa en Java

SI BEMOL

= new Nota(2);

1 / / E ~ C .

class Instrumento {

public void tocar(Nota n) {

System.out .println ("Instrumento. tocar ( ) ") ;

1

1

/ / Los objetos de viento son instrumentos
/ / dado que tienen la misma interfaz:
class Viento extends Instrumento {

/ / Redefinir el metodo interfaz:
public void tocar(Nota n) {

System. out .println ("Viento. tocar ( ) ") ;

1

1

public class Musica {

public static void afinar(1nstrumento i) {

/ / . . .
i.tocar(Nota.DO - SOSTENIDO);

1
public static void main(String[] args) {

Viento flauta = new Viento ( ) ;
afinar (flauta) ; / / Conversión hacia arriba

1

1 / / / : -

El método Musica.afinar( ) acepta una referencia a Instrumento, pero también cualquier cosa que
se derive de Instrumento. En el método main( ), se puede ver que ocurre esto pues se pasa una
referencia Viento a afinar( ), sin que sea necesaria ninguna conversión. Esto es aceptable; la in-
terfaz de Instrumento debe existir en Viento, puesto que Viento se hereda de Instrumento.
Hacer una conversión hacia arriba de Viento a Instrumento puede "estrechar" esa interfaz, pero
no puede reducirlo a nada menos de lo contenido en la interfaz de Instrumento.

Olvidando el tipo de objeto
Este programa podría parecer extraño. 2Por qué debería alguien olvidar intencionadamente el
tipo de objeto? Esto es lo que ocurre cuando se hace conversión hacia arriba, y parece que po-
dría ser mucho más directo si afinar( ) simplemente tomara una referencia Viento como argu-
mento. Esto presenta un punto esencial: si se hiciera esto se necesitaría escribir un nuevo mé-
todo afinar( ) para cada tipo de Instrumento del sistema. Supóngase que se sigue este
razonamiento y se añaden los instrumentos de Cuerda y Metal:

7 : Polimorfismo

225

/ / : c07:musica2:Musica2.java
/ / Sobrecarga en vez de conversión hacia arriba.

class Nota {

private int valor;
private Nota(int val) { valor = val; }
public static final Nota

DO-MAYOR = new Nota (O),
DO-SOSTENIDO = new Nota(l),
SI-BEMOL = new Nota(2);

1 / / Etc.

class Instrumento {

public void tocar(Nota n) {

System.out.println("Instrumento.tocar()");

}

1

class Viento extends Instrumento {

public void tocar(Nota n) {

System.out .println ("Viento. tocar ( ) " ) ;

class Cuerda extends Instrumento {

public void tocar(Nota n) {

System.out .println ("Cuerda. tocar ( ) " ) ;

1

class Metal extends Instrumento {

public void tocar (Nota n) {

System.out .println ("Metal. tocar ( ) " ) ;

1

public class Musica2 {

public static void afinar(Vient0 i) {

i. tocar (Nota. DO-MAYOR) ;

}
public static void afinar(Cuerda i) {

i . tocar (Nota. DO-MAYOR) ;

1
public static void afinar(Meta1 i) {

i. tocar (Nota. DO-MAYOR) ;

226

Piensa en Java

public static void main (String[] args) {

Viento flauta = new Viento();
Cuerda violin = new Cuerda();
Metal trompeta = new Metal ( ) ;
afinar(f1auta); / / Sin conversión hacia arriba
afinar (violin) ;
afinar (trompeta) ;

1

1 / / / : -

Esto funciona, pero hay un inconveniente: se deben escribir métodos específicos de cada tipo para
cada clase Instrumento que se añada. En primer lugar esto significa más programación, pero tam-
bién quiere decir que si se desea añadir un método nuevo como afinar( ) o un nuevo tipo de
Instrumento, se tiene mucho trabajo por delante. Añadiendo el hecho de que el compilador no emi-
tirá ningún mensaje de error si se olvida sobrecargar alguno de los métodos, el hecho de trabajar
con tipos podría convertirse en inmanejable.

¿No sería muchísimo mejor si simplemente se pudiera escribir un único método que tomara como
parámetro la clase base, y no cualquiera de las clases específicas derivadas? Es decir, ¿no sería ge-
nial que uno se pudiera olvidar de que hay clases derivadas, y escribir un código que sólo tratara
con la clase base?

Esto es exactamente lo que permite hacer el polimorfismo. Sin embargo, la mayoría de programa-
dores que provienen de lenguajes procedurales, tienen problemas para entender el funcionamiento
de esta caracterítica.

El cambio

La dificultad con Musica.java se puede ver ejecutando el programa. La salida es Viento.tocar( )
Ésta es, ciertamente, la salida deseada, pero no parece tener sentido que funcione de esa forma.
Obsérvese el método afinar( ):

public static void afinar (Instrumento i) {

/ / . . .
i .tocar (Nota. DO-MAYOR) ;

1

Recibe una referencia a Instrumento. Por tanto, ¿cómo puede el compilador saber que esta re-
ferencia a Instrumento apunta a Viento en este caso, y no a Cuerda o Metal? El compilador de
hecho no puede saberlo. Para lograr un entendimiento más profundo de este aspecto, es útil echar
un vistazo al tema de la ligadura.

7: Polimorfismo

227

La ligadura en las llamadas a métodos
La conexión de una llamada a un método se denomina ligadura. Cuando se lleva a cabo la ligadura
antes de ejecutar el programa (por parte del compilador y el montador, cuando lo hay) se denomi-
na ligadura temprana. Puede que este término parezca extraño pues nunca ha sido una opción con
los lenguajes procedurales. Los compiladores de C tienen un único modo de invocar a un método
utilizando la ligadura temprana.

La parte confusa del programa de arriba no se resuelve fácilmente con la ligadura temprana pues el
compilador no puede saber el método correcto a invocar cuando sólo tiene una referencia a un
Instrumento.

La solución es la ligadura tardía, que implica que la correspondencia se da en tiempo de ejecución,
basándose en el tipo de objeto. La ligadura tardia se denomina también dinámica o en tiempo de eje-
cución. Cuando un lenguaje implementa la ligadura tardía, debe haber algún mecanismo para de-
terminar el tipo de objeto en tiempo de ejecución e invocar al método adecuado. Es decir, el com-
pilador sigue sin saber el tipo de objeto, pero el mecanismo de llamada a métodos averigua e invoca
al cuerpo de método correcto. El mecanismo de la ligadura tardía varía de un lenguaje a otro, pero
se puede imaginar que es necesario instalar algún tipo de información en los objetos.

Toda ligadura de métodos en Java se basa en la ligadura tardía a menos que se haya declarado un
método como constante. Esto significa que ordinariamente no es necesario tomar decisiones sobre
si se dará la ligadura tardía, sino que esta decisión se tomará automáticamente.

¿Por qué declarar un método como constante? Como se comentó en el capítulo anterior, evita que na-
die superponga el método. Todavía más importante, "desactiva" ligadura dinámica, o mejor, es que, le
dice al compilador que este tipo de ligadura no es necesaria. Esto permite al compilador generar códi-
go ligeramente más eficiente para llamadas a métodos constantes. Si embargo, en la mayoría de los
casos no se obtendrá ninguna mejora global de rendimiento del programa, por lo que es mejor usar mé-
todos constantes únicamente como una decisión de diseño, y no para intenta
  • Links de descarga
http://lwp-l.com/pdf18434

Comentarios de: Polimorfismo - Piensa en Java (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad