Asociación Dinámica de Métodos

Anuncio
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Lenguajes de Programación I
Inicialización y Destrucción - Asociación Dinámica de
Métodos
Ernesto Hernández-Novich
<[email protected]>
Copyright (c) 2007
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Inicialización de Objetos
En los lenguajes orientados a objetos existe un
mecanismo especial para inicializar los objetos.
Son subrutinas denominadas constructores.
Se ejecutan automáticamente a tiempo de elaboración del
objeto.
No reservan espacio, sólo lo inicializan.
En algunos lenguajes es necesario contar con un sistema
similar para finalizar los objetos.
Son subrutinas denominadas destructores.
Se ejecutan automáticamente a tiempo de finalización del
objeto.
Generalmente sirven para liberar espacio.
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
¿Cómo escoger el constructor?
Existen lenguajes que permiten más de un constructor.
Todos con el mismo nombre, siendo necesario seleccionar
por la firma de los argumentos (C++, Java, C++).
Con nombres diferentes (Smalltalk, Eiffel).
Existen lenguajes que no permiten constructores
(Modula-3).
Existen lenguajes que sólo permiten constructores si las
clases tienen propiedades especiales (Ada).
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Modelo de Referencia vs. Modelo de Valores
Si el lenguaje usa referencias a objetos (Java, Ruby,
Pyhton, Simula)
Cada objeto es creado de forma explícita.
Es fácil asegurarse de la ejecución de los constructores.
Si el lenguaje usa valores que son objetos (C++,
Modula-3, Ada)
Los objetos pueden aparecer de forma implícita a tiempo
de elaboración.
Es crucial que los constructores sean ejecutados.
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Dificultades del modelo de valores
El ejemplo de C++
Constructores con parámetros.
foo b;
// foo::foo()
foo b(10,’x’); // foo:foo(int,char)
Constructores para clonación
foo a;
bar b;
foo c(a);
foo d(b);
// foo::foo(foo&)
// foo::foo(bar&)
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Más complicaciones en C++
Todo constructor de un argumento se denomina
Constructor para Copia.
foo
bar
...
foo
foo
a;
b;
// foo::foo()
// bar::bar()
c = a;
d = b;
// foo::foo(foo&)
// foo::foo(bar&)
!Pero no es una asignación!
foo
bar
...
c =
d =
a, c, d; // foo::foo() tres veces
b;
// bar::bar()
a;
b;
// foo::operator=(foo&)
// foo::operator=(bar&)
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Afectan el rendimiento
Una declaración como foo a = b + c se convierte en
foo t;
t = b.operator+(c);
foo a = t;
Al pasar parámetros por valor a las subrutinas, se hace
necesario un constructor de copia.
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Orden de Ejecución
Si una clase B deriva de una clase A, ¿en que orden
deben ejecutarse los constructores?
En C++, es necesario que el constructor de A se ejecute
antes que el de B. Al declarar el constructor de B, se
indican los parámetros para el constructor de A
B::B( B args ) : A( A args ) {
También se puede indicar los argumentos para atributos
class B : A {
m1_t m1;
m2_t m2;
}
B::B ( B args ) : A ( A args ),
m1 ( m1 args ),
m2 ( m2 args ) {
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Orden de Ejecución
Java tiene la misma condición de C++, pero utiliza el
modelo de referencia.
La llamada al constructor de la superclase se hace de
forma explícita usando super.
Si no se hace, entonces el compilador incluye una llamada
implícita al constructor de cero argumentos.
Los atributos que sean objetos se inicializan con una
referencia nula.
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Destrucción de Objetos
En C++, los destructores son llamados en orden inverso
de herencia.
En C++, se necesitan los destructores para liberar el
espacio de memoria reservado explícitamente.
En lenguajes con recolección de basura, los destructores
son prácticamente inútiles.
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Polimorfismo de Subtipos
Si una clase B deriva a una clase A
B tiene todos los atributos y métodos de A.
B es estructuralmente equivalente a A.
Cualquier cosa posible sobre un objeto de clase A, también
es posible sobre un objeto de clase B.
Excelente para programar de manera general
class persona { persona::imprimir_carnet() }
class estudiante : public persona { ... }
class profesor : public persona { ... }
estudiante e;
profesor
p;
persona *x = &e, *y = &p;
e.imprimir_carnet();
p.imprimit_carnet();
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
¿Qué pasa al redefinir métodos?
Si redefinimos imprimir_carnet en ambas subclases.
e.imprimir_carnet() invoca al método de la clase
estudiante.
p.imprimir_carnet() invoca al método de la clase
profesor.
¿A cuál método debe invocar x->imprimir_carnet()?
Si la decisión depende del tipo de x se trata de
asociación estática de métodos y se decide a tiempo de
compilación.
Si la decisión depende del tipo del objeto apuntado por x
se trata de asociación dinámica de métodos y se decide
a tiempo de ejecución.
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Métodos Virtuales y No Virtuales
Muchos lenguajes usan asociación dinámica de métodos
siempre (Python, Ruby, Perl, Smalltalk).
Otros lenguajes tienen ambos métodos, pero usan el
dinámico por omisión (Java, Eiffel).
Para indicar que un método debe asociarse estáticamente
se le agrega una palabra clave (final en Java, frozen
en Eiffel).
Esto impide que sean redefinidos en las subclases y puede
optimizarse su invocación.
Otros lenguajes prefieren el estático por omisión (C++, C#,
Ada).
Para indicar que un método debe asociarse dinámicamente
se le agrega una palabra clave (virtual en C++).
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Clases Abstractas
Se dice que un método es abstracto si se omite el cuerpo.
Una Clase Abstracta es aquella que tiene al menos un
método abstracto.
No pueden ser instanciadas.
Sólo sirven como base para clases concretas.
Los métodos abstractos sirven como enlace para proveer
asociación dinámica de métodos.
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Implantación de la Asociación Dinámica
Todo objeto debe contener suficiente información para
decidir los atributos y métodos adecuados a tiempo de
ejecución.
Cada objeto se representa como un registro cuyo primer
campo contiene una referencia a la tabla de métodos
virtuales (vtable).
La vtable es un arreglo cuya i-ésima entrada apunta al
segmento de código del i-ésimo método virtual del objeto.
Inicialización y Destrucción de Objetos
Construcción de vtables
Para la clase base
class foo {
int a;
double b;
char c;
public:
virtual void k(...
virtual int l(...
virtual void m(...
virtual double n(...
} F;
Asociación Dinámica de Métodos
Inicialización y Destrucción de Objetos
Construcción de vtables
Para una clase derivada
class bar : public foo {
int w;
public:
void m(...
virtual double s(...
virtual char *t(...
} B;
Asociación Dinámica de Métodos
Inicialización y Destrucción de Objetos
Asociación Dinámica de Métodos
Herencia Múltiple
Si dos clases ancestrales proveen el mismo método:
¿Ambas son accesibles?
¿Cuál debe utilizarse?
Si dos clases ancestrales derivan de un ancestro común:
¿Hay una o dos copias de los métodos del ancestro?
¿Cómo representar las instancias de las subclases?
Interfaces vs. Herencia Múltiple
Descargar