26
II

Programacion Orientada a Objetos.pdf

Embed Size (px)

Citation preview

Page 1: Programacion Orientada a Objetos.pdf

II

Capítulo 1.- PROGRAMACIÓN ORIENTADA A OBJETOS

1

INTRODUCCIÓN AL ENFOQUE O.O ..............................................................................1

2

CONCEPTOS BÁSICOS DE ORIENTACIÓN A OBJETOS ............................................2

2.1

OBJETOS.........................................................................................................................2

2.1.1

Identidad...................................................................................................................3

2.1.2

Encapsulación y ocultación de datos.........................................................................3

2.1.3

Métodos y mensajes...................................................................................................4

2.2

CLASES...........................................................................................................................5

2.2.1

Herencia ...................................................................................................................5

2.2.2

Organización y relaciones entre objetos....................................................................8

2.2.3

Polimorfismo y Ligadura Dinámica.........................................................................10

3

LENGUAJES ORIENTADOS A OBJETOS. ....................................................................11

3.1

ORÍGENES DE LOS LENGUAJES ORIENTADOS A OBJETOS....................................................11

3.2

CLASIFICACIÓN .............................................................................................................12

3.3

VENTAJAS E INCONVENIENTES. ......................................................................................13

3.4

PRINCIPALES LENGUAJES ORIENTADOS A OBJETOS ...........................................................14

3.4.1

Simula.....................................................................................................................14

3.4.2

Smalltalk .................................................................................................................14

3.4.3

Objective-C.............................................................................................................15

3.4.4

C++........................................................................................................................16

3.4.5

Ada .........................................................................................................................17

3.4.6

Object-Oriented Pascal. ..........................................................................................17

3.4.7

Turbo Pascal...........................................................................................................18

3.4.8

Eiffel .......................................................................................................................18

3.4.9

Java ........................................................................................................................19

3.5

ELECCIÓN DE UN LENGUAJE OO.....................................................................................24

Page 2: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-1

Capítulo 1 PROGRAMACIÓN ORIENTADA A OBJETOS

1 Introducción al enfoque O.O

Durante los últimos años, la Programación Orientada a Objetos (OOP) ha tomado gran

importancia. El término OOP indica más una forma de diseño y una metodología de desarrollo que un

lenguaje de programación, ya que en realidad se puede aplicar el Diseño Orientado a Objetos (OOD) a

cualquier tipo de lenguaje de programación.

A menudo se confunde la Orientación a Objetos con sistemas de ventanas, iconos y similares,

Interfaces Gráficas de Usuario. Esto es debido a que se usan técnicas orientadas a objetos para construir

estos entornos. También se piensa que todo lo programado por lenguajes orientados a objetos es O.O.P.

Esto no es cierto, ya que incluso es posible hacer O.O.P. en lenguajes procedimentales clásicos.

Aspectos importantes que determinan el desarrollo de software son:

� PORTABILIDAD. El software desarrollado debe funcionar independientemente del

hardware y del entorno de funcionamiento o Sistema Operativo sobre el cual se ejecute.

� PRODUCTIVIDAD. Uno de los principales objetivos es simplificar el proceso de

desarrollo de Software, para lo cual es fundamental reutilizar componentes.

� MANTENIMIENTO. Constituye una de las etapas más costosas en el

desarrollo de software que, por tanto, habrá de intentarse optimizar. Es fundamental estructurar

bien el programa para prever futuros cambios o modificaciones.

� CALIDAD. A la hora de producir software, no hay que olvidar que se deben de

desarrollar productos de calidad, dada a partir de una serie de aspectos como robustez,

fiabilidad, eficiencia, flexibilidad,..

Cualquier metodología de programación debe intentar producir programas portables, reducir los

tiempos de desarrollo y los costes de mantenimiento, así como mejorar la calidad del producto.

Los principales problemas de las metodologías de programación actuales son :

� Creciente complejidad de las aplicaciones: Los requisitos cada vez más

ambiciosos de las aplicaciones, reflejan una sofisticación en la demanda de software.

� Limitaciones en la modelización de problemas no estructurados. Las actuales

metodologías estructuradas dificultan la modelización y resolución de problemas complejos no

estructurados. Siguiendo una metodología estructurada los sistemas se descomponen en una

jerarquía de módulos. Estos se diseñan para transformar entradas y salidas bien definidas.

Este enfoque es el más apropiado para su empleo en problemas estructurados en donde el

comportamiento del software se conoce y se puede describir en base a algoritmos de

transformación de datos. El software se estructura en base a la solución del problema en vez de

enfocarlo al problema en sí mismo. Esto puede conducir a una separación conceptual entre el

problema del mundo real y su representación e implementación informática.

� Difícil reutilización del software. Es normal que se construyan y reconstruyan una

y otra vez módulos muy parecidos funcionalmente. Muchos de los intentos de crear librerías de

componentes de software reutilizables no han tenido mucha implantación debido sobre todo a

los problemas inherentes a su reutilización. Cualquier simplificación del proceso de desarrollo

del software pasa por la reutilización de componentes ya implementados.

� Mantenimiento difícil y costoso. El mantenimiento de las aplicaciones supone el

coste más importante durante el ciclo de vida. Debido a la evolución que sufren todas las

aplicaciones, a menudo se introducen ampliaciones y se desarrollan nuevos entornos de

operación, lo cual argumenta que el mantenimiento sea una actividad esencial. Como durante el

desarrollo de las aplicaciones no se han tenido en cuenta futuros cambios, es frecuente

encontrar programas mal estructurados en los cuales es difícil la incorporación de nuevos

módulos o estructuras de datos.

Page 3: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-2

El desarrollo de la OOP empieza a destacar durante la década de los 80, partiendo de la

programación estructurada, a la que engloba, y dotando al programador de nuevos elementos para el

análisis y desarrollo de software. Así, las metodologías orientadas a objetos pueden facilitar la producción

de sistemas cada vez más complejos, permiten modelar problemas no estructurados, incrementan la

productividad gracias a la reutilización de objetos y facilitan el mantenimiento.

La orientación a objetos puede describirse cómo el conjunto de disciplinas que desarrollan y

modelizan software que facilitan la construcción de sistemas complejos a partir de componentes.

El atractivo de la orientación a objetos es que proporciona conceptos y herramientas con las cuales

se modela y representa el mundo real tan fielmente como sea posible.

La OOP proporciona las siguientes VENTAJAS sobre otros lenguajes de programación:

� Uniformidad pues la representación de los objetos lleva implícita tanto el análisis

como el diseño y codificación de los mismos.

� Compresión: tanto los datos que componen los objetos, como los procedimientos

que los manipulan, están agrupados en clases, que se corresponden con las estructuras de

información que el programa trata.

� Flexibilidad: Al tener relacionados los procedimientos que manipulan los datos

con los datos a tratar, cualquier cambio que se realice sobre ellos quedará reflejado

automáticamente en cualquier lugar donde estos datos aparezcan.

� Reusabilidad: La noción de objeto permite que programas que traten las mismas

estructuras de datos reutilicen las definiciones de objetos empleadas en otros programas e

incluso los procedimientos que los manipulan. De esta forma, el desarrollo de un programa

puede llegar a ser una simple combinación de objetos ya definidos donde éstos están

relacionados de una manera particular.

La OOP no sustituye a ninguna metodología ni lenguaje de programación anterior, es un enfoque

distinto. Todos los programas que se realizan según OOD se pueden realizar igualmente mediante

programación estructurada. Su uso en la actualidad se justifica porque el desarrollo de todas las nuevas

herramientas basadas en una interface de usuario gráfico como Windows, X-Window, ... es mucho más

sencillo.

2 Conceptos básicos de orientación a objetos

2.1 Objetos

La POO se basa en diseñar programas mediante el uso de OBJETOS, identificando componentes o

actores que mediante unas determinadas acciones, interaccionando entre ellos, resuelven el problema a

resolver. Los objetos son por tanto abstracciones de elementos relacionados con el área del problema,

diseñados para reflejar su comportamiento. Casi todo puede ser considerado un objeto: el dinero, el

helicóptero, una persona, una tabla, un ordenador, un avión, un diccionario, la ciudad o la capa de ozono.

Los objetos representan cosas, simples o complejas. Principalmente, un objeto complejo es aquel que está

compuesto por otros objetos, como por ejemplo un objeto ‘texto’ que está compuesto por otros objetos

‘párrafos’ más pequeños. Una antena parabólica es un objeto complejo y real, y puede ser representado

por un objeto complejo en un sistema informático. El objeto que representa a la antena estará formado por

otros objetos que representan el receptor, el transmisor, el motor orientador de la antena ... etc.

Smith y Tockey sugieren que “un objeto representa un elemento, unidad o entidad individual e

identificable, ya sea real o abstracta, con un papel bien definido en el dominio del problema”.

En algunos lenguajes, como por ejemplo SmallTalk, la Orientación a Objetos es pura, y todos los

posibles elementos del propio lenguaje son objetos. En otros lenguajes, los más habituales, algunas cosas

no son objetos, sino atributos, valores o características de objetos, representado por tipos de datos como

entero, flotante .. etc. Algunas de ellas son simplemente atributos de los objetos como el color, el tamaño y

la velocidad. Los atributos reflejan el estado de un objeto (la velocidad del objeto avión o el tamaño de un

objeto edificio).

Un OBJETO es la integración de tres aspectos:

� Relaciones, permiten que el objeto se integre en la organización de la que forma

Page 4: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-3

parte junto con otros objetos. Las relaciones pueden ser de tipo jerárquico (herencia) o

semántico, como en el caso de los objetos que componen la antena parabólica.

� Propiedades (atributos), distinguen un objeto de los restantes (tamaño, posición,

color, ...). Cada propiedad tendrá un determinado valor. Las propiedades de un objeto pueden

ser heredadas por sus descendientes.

� Métodos (operaciones), conjunto de cosas que puede hacer un objeto (estudiar,

caminar, trabajar, rotar, volar, etc.). Un método es un procedimiento o función que altera el

estado de un objeto o hace que el objeto envíe un mensaje, es decir, que devuelva valores. Los

métodos pueden ser heredados por sus descendientes.

Es decir, los objetos conocen cosas y hacen cosas. Las cosas que un objeto conoce son sus

atributos; este conjunto de atributos también es conocido como su estado. Las cosas que puede hacer son

sus métodos. El conjunto de métodos de un objeto es conocido como su comportamiento. El conjunto de

métodos y atributos se conoce muchas veces como miembros. Ejemplo: Una máquina expendedora de refrescos puede aceptar monedas. Esta es una propiedad estática (es decir, fija), lo

que significa que es una característica esencial de la máquina. En cambio, la cantidad actual de monedas que ha

aceptado en un momento dado representa el valor dinámico de esta propiedad (atributo). El mecanismo que acepta las

monedas y devuelve un refresco a cambio es un conjunto de métodos: su comportamiento.

Todo objeto tiene un estado, exhibe algún comportamiento bien definido y tiene una identidad única (como se verá en el siguiente apartado). El estado de un objeto abarca todas las propiedades (normalmente estáticas) del mismo más los valores actuales (normalmente dinámicos) de cada una de esas propiedades.

El comportamiento se refiere a cómo actúa y reacciona un objeto, en términos de sus cambios de estado y paso de mensajes.

2.1.1 Identidad

Una casa, una persona, una tabla, una calculadora, una pieza del juego de ajedrez, son objetos de la vida cotidiana. A su vez, un párrafo en un documento o una ventana en Windows son objetos de uso común en programación. Cada objeto existe y tiene entidad por sí mismo. La identidad expresa que aunque dos objetos sean exactamente iguales en sus atributos, son distintos entre sí. De esta forma, incluso una serie de coches recién salidos de fábrica son distintos los unos de los otros. Esto tiene importancia cuando descendemos al nivel de programación. Aquí, cada objeto tiene un controlador por el cual se identifica. Éste puede ser una variable, una estructura de datos, una cadena de

caracteres, etc. El controlador será distinto para cada uno de los objetos, aunque las referencias a éstos sean uniformes e independientes del contenido, permitiendo crear agrupaciones de objetos con el mismo tratamiento (clases). Ejemplo: En Java, se utilizan las referencias para apuntar a los objetos.

class a {}class ppal {static public void main(String[] args){

a refa = new a; // refa es una referencia.}

En C++, se pueden utilizar punteros o variables. class a{};int main(void){

a *ptra = new a;// ptra es un puntero al objeto de la clase “a”a obja; // obja es una variable.

// Representa a un objeto de la clase a.}

2.1.2 Encapsulación y ocultación de datos

La encapsulación es el término de OO que describe la vinculación de unas operaciones y estado a un objeto particular. Un objeto es la integración de atributos y métodos. Los datos de la programación tradicional son ahora atributos de un objeto y las funciones los métodos que se utilizan para procesar los atributos de ese

Page 5: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-4

objeto. Esto quiere decir que todos esos datos y funciones, en lugar de estar dispersos, como en programación estructurada, se encapsulan en una única unidad, el objeto.

La organización interna del objeto es inaccesible desde el exterior (ocultamiento de la

información). Las partes ocultas o encapsuladas de un objeto son su implementación privada, o lo que

es lo mismo se dice que son privados. Se dice que los atributos y los métodos visibles son públicos y

forman la interface del objeto. Ejemplo: Esto es similar a un módulo de programación estructurada, en el que ciertas funciones son visibles desde el exterior,

públicas, mientras que otras son privadas, no son accesibles desde el exterior porque sólo se utilizan localmente en el

módulo, y los programas que utilicen ese módulo no necesitan conocer esas funciones privadas.

Cada objeto mantiene sus propios datos internos y los usuarios de un objeto pueden acceder y

manipular los datos internos solamente a través de sus métodos, de tal forma que la interface de un objeto

es su conjunto de métodos públicos. Así, detalles internos de la implementación de un objeto como

algoritmos o representaciones internas de datos, no son visibles. Esto refuerza el ocultamiento de la

información y permite un alto nivel de abstracción. Ejemplo: De la misma forma que no tenemos acceso a las operaciones internas que realiza un medidor de combustible en un

coche para indicarnos la cantidad de combustible disponible, no necesitamos saber, no tenemos por qué tener acceso, a

las operaciones internas de un objeto que representa un altímetro de un avión en una aplicación; sólo es necesario

conocer el método del objeto del cuál se obtiene esa altura, no cómo el objeto altímetro interacciona con el altímetro

físico.

Esto no quiere decir que sea imposible conocer información de un objeto, sino que las peticiones de

información a un objeto deben cursarse a través de mensajes al objeto con el fin de realizar determinada

operación. La respuesta a esa petición será la información solicitada siempre que el objeto compruebe que

el solicitante tiene acceso a ella.

El ocultamiento de información facilita que los usuarios de un objeto no estén expuestos al peligro

cuando su realización cambia mientras no haya cambiado la interface. Entonces los programas que

utilizaban el objeto pueden seguir funcionando sin alteración alguna. Ejemplo: Si el objeto altímetro anterior cambia su forma de interaccionar con el altímetro real del avión, no es necesario

cambiar el resto de objetos que utilizan ese objeto altímetro a menos que el método del que se obtiene la altitud hay

cambiado también. Los miembros públicos se denotan normalmente como “public”, y los privados, como “private”.

La encapsulación y el ocultamiento de información son extremadamente útiles al modificar código

(ya que se restringe la propagación de cambios). También se fomenta la reusabilidad, ya que el código

puede ser utilizado como una tecnología de caja negra (igual que los circuitos integrados en la industria

electrónica).

2.1.3 Métodos y mensajes

Los métodos son el mecanismo de acceso y manipulación de los datos del objeto, constituyen la

interface del objeto. Cada método está constituido por un conjunto de instrucciones escritas en un lenguaje

de programación estructurado determinado, asociadas a un objeto determinado y cuya ejecución sólo

puede desencadenarse a través de un mensaje recibido por este o por sus descendientes.

Los objetos se comunican a través del paso de mensajes. En la práctica, esto supone la ejecución

de un método en un objeto determinado.

Un mensaje le dice a un objeto lo que tiene que hacer, identificando un método y los operandos

necesarios para su ejecución. Los objetos reciben, interpretan y responden a mensajes procedentes de otros

objetos.

Un mensaje consiste en una dirección (a cuál o cuáles objetos se envía) y una instrucción formada

por un nombre de método y 0 o más parámetros:

OBJETO.metodo [parámetros]

Ejemplo: Supongamos el conjunto de objetos de los EMPLEADOS de una empresa. Para un empleado concreto, queremos

calcular su salario mensual, pero para ello se necesita conocer el número de horas trabajadas. Se envía un mensaje al

objeto, EMPLEADO23, de activar CALCULAR_SALARIO con horas_trabajadas determinadas:

EMPLEADO23.CALCULAR_SALARIO(horas_trabajadas)

Ante este mensaje, el receptor (EMPLEADO23) ejecutará su método CALCULAR_SALARIO (siempre que el

Page 6: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-5

emisor tenga permiso para solicitar dicha operación), o, en caso de no poder procesar el mensaje, se devolverá un

mensaje de error.

2.2 Clases

Una clase permite describir objetos similares mediante la definición de sus estructuras de datos y

métodos comunes. Las clases son plantillas para objetos, permitiendo la agrupación de objetos que

comparten las mismas propiedades y comportamiento. Así, existen rectángulos de varios tamaños, pero

todos ellos pertenecen a la clase rectángulo, que define los atributos comunes para todos ancho y alto, a

la vez que el método dibujar, también común para todos. Ejemplo: las clases funcionan como plantillas de la misma forma que es posible declarar en Pascal o en C un record o struct,

respectivamente; sin embargo, este record o struct no es utilizable hasta que se declara una variable o un puntero del

mismo. Según esta anlogía, el record sería la clase y las variables los objetos. De hecho, en C++ esto es exactamente

así.

Ejemplo: la clase empleado describe los grupos de datos y la propiedades comunes a todos los empleados de una empresa. Un

objeto empleado describe a un empleado particular. La clase empleado contendrá métodos como

modificar_dirección_empleado, calcular_salario_empleado, ...

Ejemplo: Se puede hablar de la clase Mamífero, que representa las características comunes a todos los mamíferos. Para

identificar a un mamífero particular en esta clase, hay que hablar de “este mamífero” o “aquel mamífero”.

Ejemplo: supongamos las cartas de una baraja. Cada objeto de esta clase es distinto, pero todos ellos reúnen una serie de

atributos comunes. Todas están identificadas por un número o una letra, pertenecen a un grupo, etc. A su vez,

existen varias operaciones que también son comunes a todas ellas: pueden ser repartidas, descartadas, etc. Una superclase es una clase de más alto nivel que agrupa otras clases con propiedades y funciones

comunes, por tanto, los objetos (también llamados instancias de una clase determinada) de esas otras

clases son también objetos (instancias) de la superclase. Las clases que son agrupadas por una superclase

son sus subclases.

Las propiedades de una clase deben cumplir una serie de premisas:

� Deben ser significativas dentro del entorno de la aplicación. Es decir, deben servir

para identificar claramente y de manera única a cada uno de los objetos. Ejemplo: en una aplicación de clasificación de libros, los atributos asociados a cada uno serán, por ejemplo:

editorial, autor, número de edición, ISBN, etc. Estas aplicaciones identifican claramente cada volumen.

Si la aplicación va destinada a la encuadernación, los atributos serán: ancho, alto, largo, tipo de

encuadernación, tipo de papel, volumen, etc. � El número de propiedades debe ser el mínimo para realizar todas las operaciones

que requiere la aplicación. Ejemplo: en el ejemplo anterior, se identifica el mismo objeto con atributos distintos. ¿Sería deseable identificar un objeto

con todos sus atributos? Sólo en el caso de que los objetos que definamos vayan a ser utilizados en más de una

aplicación, debemos extender sus atributos más allá de lo imprescindible, con el objetivo de dar soporte a las

operaciones definidas en el resto de las aplicaciones.

Ejemplo: A continuación, se muestra un pequeño programa en Java que declara una clase e instancia varios objetos (r1 y

r2) de esa clase.

class rectangulo {

public int ancho, alto;};public class ppal {

public static void main(String[] args){

rectangulo r1= new rectangulo;rectangulo r2 = new rectangulo;

r1.ancho = 5;r1.alto = 10;r2.ancho = 6;r2.alto = 7;

}};

2.2.1 Herencia

La herencia designa la facultad de los objetos de compartir propiedades y operaciones entre ellos.

Como la herencia humana, existen unos determinados objetos hijo que heredan las propiedades y atributos

Page 7: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-6

de otros objetos padres.

La herencia es la forma normal de estructurar los programas bajo OOP y se normalmente3 se

expresa a partir de las clases. Se trata de crear nuevas clases de objetos a partir de otras ya existentes, es

decir, de reutilizar el comportamiento de una clase en la definición de otras nuevas. Cualquier clase hereda

la declaración de los atributos y los métodos de su superclase, pudiendo estas subclases especializarse

añadiendo una declaraciones de atributos adicionales y declaraciones de métodos propios o incluso

cambiando los atributos y métodos heredados. Ejemplo: una subclase director de la clase empleado heredará toda la estructura y los métodos de la clase original y podrá

contener datos o métodos adicionales.

Semánticamente, la herencia denota una relación “es un”. Ejemplo: un oso es un tipo de mamífero, una casa es un tipo de bien inmueble, y quicksort es un tipo particular de

algoritmo de ordenación. Una de las razones para emplear la herencia es que permite la reutilización del código de

proyectos anteriores, permitiendo la modificación (o especialización) de aquellos aspectos que no

concuerden exactamente con las necesidades de nuestra aplicación.

En las jerarquías que establecen las relaciones de herencia, a medida que descendemos de nivel,

cada nivel aporta un grado más de especialización sobre el nivel inmediatamente superior. Para ello, el

objeto hijo aporta nuevas propiedades y operaciones a las del padre, llegando incluso a redefinir alguna de

las operaciones heredadas de éste.

En cambio, si partimos del nivel de clases inferiores hacia los niveles superiores, cada nivel supone

una generalización del nivel inmediatamente inferior.

Existen dos tipos fundamentales de herencia: simple y múltiple.

La clase que se sitúa en el primer nivel superior se denomina clase raíz, mientras las clases de los

niveles inferiores se denominan clases hoja o terminales. El resto se denominan clases intermedias.

Normalmente, los objetos se instancian de clases terminales o muy cercanas a ellas.

Por tanto los objetos contienen tanto miembros (atributos y métodos) propios (definidos en su

clase) como heredados.

2.2.1.1 Herencia Simple

Se produce cuando la clase que recibe la herencia tiene un sólo padre, como en el ejemplo de la

figura:

� De atributos: Las propiedades de una clase son heredadas automáticamente por todos sus

descendientes. Esto quiere decir que un objeto tiene propiedades de su clase y propiedades de las

clases heredadas. Las características que definen la herencia de las propiedades son:

� Para reducir al máximo la redundancia, una propiedad debe definirse en la posición más

elevada posible de la jerarquía.

� Las excepciones no presentan ningún problema, pues pueden resolverse definiendo de

nuevo la misma propiedad en un nivel más bajo.

� Si un objeto puede heredar valores diferentes de una propiedad de más de uno de sus

antepasados, la heredará de su antepasado más próximo.

3 Excepto en ciertos lenguajes Orientados a Objetos. Ver el apartado “elección de un lenguaje OO”.

FIGURA

CIRCULO RECTANGULO TRIANGULO

CUADRADO

Page 8: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-7

� De métodos. La herencia de los métodos permite aumentar la reutilización de software y

simplifica, por tanto, el diseño. Además, facilita la programación, reduce redundancias y simplifica la

corrección de los programas. Ejemplo: Un programa en Java en el que la clase estudiante hereda de la clase persona. La herencia se indica en Java con la

palabra clave extends. class persona {

public String nombre;}class estudiante extends persona {

public String titulacion;}public class ppal {

public static void main(String[] args){

estudiante paula = new estudiante;paula.nombre = “Paula Fernández”;paula.titulación = “Ingeniería Informática”;

}}

2.2.1.2 Herencia Múltiple

Se produce cuando el objeto que hereda tiene más de un padre o alguno de sus antepasados tiene

varios padres. Es decir, cuando un objeto puede heredar de varios y no sólo de uno como ocurre en la

herencia simple.

La herencia múltiple ofrece la posibilidad de definir clases híbridas que comparten las propiedades

de dos o más clases predefinidas. Es difícil de implementar ya que para determinar si un objeto hereda una

propiedad o un método puede que haya que seguir caminos por más de un padre.

Además pueden darse conflictos debidos a que un objeto herede la misma propiedad o método de

dos objetos situados al mismo nivel o a distinto nivel. Este tipo de situaciones se da cuando una clase

hereda 2 o más versiones de un método provenientes de los distintos ancestros, y es inevitable en el caso

de la herencia repetida, que se produce cuando una clase hereda de otras que a su vez heredan de una

clase común.

♦ Esta herencia suele producir los conflictos conocidos como Conflicto de nombres. Sucede

cuando el nombre de un método o atributo existe en más de una clase de nivel superior:

Los lenguajes de programación resuelven así el conflicto de nombres: � Smalltalk lo considera ilegal y rechaza la compilación � Eiffel permite renombrar los elementos para que no haya ambigüedad. Para nuestro

ejemplo, se pondría nombre_profesor, nombre_investigador y nombre_profesor_universitario. � C++ exige que todas las referencias de nombre califiquen la fuente de su declaración

(es decir, se indica delante del atributo la clase de la cual proviene). Ejemplo: poniendo p.profesor::nombre, p.investigador::dirección, obtendríamos de p el nombre declarado en

profesor y la dirección de la clase investigador.

� Otros lenguajes utilizan: una lista de precedencia de clases, o una lista de

precedencia del usuario y, si no sucede así, se fija una estrategia de búsqueda en el grafo de

herencia (primero en profundidad o en amplitud).

Dentro de la herencia múltiple, se pueden distinguir otros dos tipos de herencia:

� Herencia selectiva (o parcial) que permite decidir qué métodos se heredan y cuáles no.

Esto complica sintácticamente la definición de una clase, lo que hace que sean pocos los

PERSONA

PROFESOR INVESTIGADOR

PROFESOR

UNIVERSITARIO

Page 9: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-8

lenguajes que la adoptan. Ejemplo C tiene 2 superclases: A y D. Mediante herencia selectiva, C hereda selectivamente algunas atributos y métodos de

A y de D.

� Herencia no selectiva que fuerza a que todos los atributos y métodos sean heredados.

Por otro lado, en términos del comportamiento con respecto a los métodos que se heredan, se

puede hacer la distinción entre herencia estricta y no estricta, refiriéndose a la imposibilidad o

posibilidad de redefinir el significado (modificar el cuerpo de la función) de un método

determinado, respectivamente.

2.2.2 Organización y relaciones entre objetos

2.2.2.1 Organización jerárquica Las clases se organizan jerárquicamente si tenemos en cuenta la relación de herencia. Esta

organización es simple cuando se pueda representar por medio de un árbol y compleja cuando existe

herencia múltiple. En cualquier caso se pueden distinguir tres niveles diferentes de clases:

� RAÍZ (o SUPERCLASE): Es una clase, que suele ser único y especial, caracterizado por estar

situado en el punto más elevado de la organización jerárquica.

� CLASES INTERMEDIOS, descienden directamente o indirectamente de la raíz y a su vez

tienen descendientes. Representan clases de objetos y reciben nombres genéricos que denotan

al conjunto de objetos al que representan: personal, facturas, clientes,... En general reciben el

nombre de clases si descienden directamente de la raíz o subclases si descienden de una clase o

otra subclase. Otra clasificación de los objetos intermedios se basa en si sus descendientes son

también intermedios o son terminales. A los primeros se les conoce entonces como clase

abstracta y a los segundos clase de objetos terminales.

� CLASES TERMINALES, descienden de una clase o una subclase y no tienen descendientes.

Los objetos normalmente se instanciarán de estas clases. Ejemplo: Un programa en Java en el que la clase estudiante hereda de la clase persona. Las clases creadas en Java tienen

siempre, aunque no se haga explícito, una clase padre llamada Object. Object es la clase padre de persona, y

persona la de estudiante. En este ejemplo estudiante es la clase terminal, aunque creamos objetos de ella y de

persona. class persona {

public String nombre;}class estudiante extends persona {

public String titulacion;}public class ppal {

public static void main(String[] args){

estudiante paula = new estudiante;paula.nombre = “Paula Fernández”;paula.titulación = “Ingeniería Informática”;

}}

2.2.2.2 Relaciones jerárquicas entre clases

Una clase es padre de otra cuando existe una relación jerárquica directa entre ellas, según la cual la

G

D

B

A

E C

Page 10: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-9

primera se encuentra situado inmediatamente encima de la segunda en el árbol jerárquico. Si una clase es

padre de otra, la segundo es hija de la primera.

Una organización jerárquica es simple cuando una clase sólo puede tener un padre, y compleja

cuando puede tener varios padres.

Si B es padre de C, puede suceder :

1. B es un objeto intermedio, B y C son conjuntos de objetos y C es un subconjunto de B, C ⊂ B.

Si además B ⊂ A, entonces C ⊂ A. Es decir si C es hijo de B y B es hijo de A, entonces C es

descendiente de A (o lo que es lo mismo, la herencia es transitiva).

2. C es una clase terminal, C ⊂ B, y B ⊂ A, entonces C ⊂ A. Es decir si C es hijo de B y B es

hijo de A, A es antepasado de C.

O dicho de otra forma:

� A es antepasado de B, si A es padre de B o si A es padre de un antepasado de B.

� B es descendiente de A, si B es hija de A o si es hija de un descendiente de A.

2.2.2.3 Abstracción

Shaw define abstracción como “una descripción simplificada o especificación de un sistema que

enfatiza algunos de los detalles o propiedades del mismo mientras suprime otros. Una buena abstracción

es aquella que enfatiza detalles significativos al lector o usuario y suprime detalles que son, al menos por

el momento, irrelevantes o causa de distracción”. Una abstracción denota las características esenciales de

un objeto que lo distinguen de todos los demás tipos de objeto y proporciona así fronteras conceptuales

respecto a la perspectiva del observador.

La abstracción es una técnica de programación que permite definir nuevos tipos de datos por el

usuario. La esencia de la abstracción es similar al uso de un tipo de dato de un lenguaje de programación,

cuyo uso se realiza sin saber como está representado o implementado.

Las abstracciones deben ser completas, es decir, los objetos deben abstraer y encapsular tanto los

datos como sus procesos. Las cosas se perciben no sólo a través de sus propiedades, sino a través de su

comportamiento: se conocerán por su estado.

Una abstracción se centra en la vista externa de un objeto, de modo que sirva para separar el

comportamiento esencial de un objeto de su implementación. Definir una abstracción significa describir una

entidad del mundo real, no importa lo compleja que pueda ser, y a continuación utilizar esta descripción en

un programa.

El uso de un objeto por vía de su especificación como tipo abstracto o clase abstracta significa que,

si su aspecto interno experimenta modificaciones, otras partes del sistema no se verán afectadas.

Un método abstracto es un método que declara una funcionalidad que debe ser implementada en

todas las clases derivadas de la clase en que se vaya a utilizar. En otras palabras, a través de un método tal

indicamos lo que deberían poder hacer los objetos de dichas subclases. No se implementa en la clase base,

sino que cada subclase debe tener su propia implementación. Ejemplo: Una clase cerradura esconde a vista de todos la combinación que la abre. Es por tanto un atributo privado. Para

abrir la cerradura, tenemos un método público al que hay que pasarle la combinación real. Para darle a la

cerradura su combinación inicial, utilizamos un constructor, un método especial de Java que se llama igual que la

clase y que sirve precisamente para dar valores iniciales. import java.io.*;class cerradura {

private int combinacion;public bool abreCerradura(int c) {

if (c==combinacion)return true;

else return false;}cerradura(int c) { combinación = c; }

}public class ppal {

public static void main(String[] args){

cerradura candado = new cerradura(123);

System.out.println(candado.abreCerradura(456));//‘false’System.out.println(candado.abreCerradura(123));//‘true’

}}

Page 11: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-10

Ejemplo: Un ejemplo se muestra a continuación en Java, donde se declara la clase abstracta Figura. Las figuras

concretas, como Círculo o Rectángulo se derivan de la clase Figura. La clase Figura puede contener atributos

comunes a todas las clases; también se pueden declarar métodos que se implementan genéricamente en la clase

abstracta Figura. Pero por ejemplo, el método Área es imposible indicar cómo calcularla en la clase abstracta, es

dependiente de las figuras concretas, por lo tanto se define como método abstracto y su implementación se define

en las clases derivadas Círculo y Rectángulo. Como contrapartida, no es posible instanciar objetos de la clase

figura. import java.io.*;abstract class figura {

abstract public float calculaArea();}class rectangulo extends figura {

private float ancho, alto;public float calculaArea() { return ancho * alto; }rectangulo(int a, int l) { ancho = a; largo = l; }

}class circulo extends figura {

private float radio;public float calculaArea() { return radio*radio*3.1415927; }circulo(int r) { radio = r;}

}public class ppal {

public static void main(String[] args){

rectangulo r = new rectángulo(6,10);circulo c = new circulo(5);System.out.println(r.calculaArea()); // 60System.out.println(c.calculaArea()); // 78.53

}}

2.2.3 Polimorfismo y Ligadura Dinámica

2.2.3.1 Polimorfismo

En un sistema orientado a objetos los mismos nombres pueden ser utilizados para denominar

diferentes cosas, en diferentes contextos. Esta propiedad es el polimorfismo, la cual dota a los sistemas de

una gran flexibilidad.

El polimorfismo indica la posibilidad de definir varias operaciones con el mismo nombre,

diferenciándolo únicamente en los parámetros de entrada. Dependiendo del objeto que se introduzca como

parámetro de entrada, se elegirá automáticamente cuál de las operaciones se va a realizar. Ejemplo: director, secretaria, contable son subclases de empleado. El método calcular_salario_empleado puede ser diferente

para cada subclase, pero común a todos ellos (es decir, a todos ellos se les puede calcular el sueldo de una u otra

forma).

En algunos lenguajes OOP esta propiedad viene asociada a otra conocida como operator

overloading (sobrecarga de operadores), que permite la redefinición de operadores como “+”, “-", ... Ejemplo: esto es lo que sucede cuando el signo + se emplea para denotar la adición entera o real, de modo que el mensaje

“sumar 1” invoca procedimientos completamente diferentes, pero conviene utilizar la misma notación “+” para ambos

propósitos, porque contribuye a su comprensión y hace que el lenguaje sea más fácil de aprender y recordar.

También permiten sobrecarga de métodos, es decir, varios métodos que tienen el mismo nombre

(la misma signatura), pero el número de parámetros o los tipos de la lista de parámetros es distinto.

Esta propiedad es una poderosa herramienta para simplificar el diseño de aplicaciones, pero hay

que tratarla con precaución. El error más común provocado por el uso del polimorfismo es que, en un

afán de simplificar, si se utilizan siempre los mismos nombres en las operaciones, desvirtualizamos el

nombre del operador.

La gran ventaja del polimorfismo es permitir la realización de las clases que definen un programa de

forma totalmente independiente al programa donde se utilizan.

El polimorfismo facilita la reutilización de software, haciendo posible implementar software

genérico que se pueda aplicar no sólo a objetos existentes, sino también a objetos que sean añadidos en

etapas futuras del desarrollo. Ejemplo: Tomando las clases que se declaran en el ejemplo de la sección ‘Abstracción’, es decir, figura, rectángulo y círculo,

podemos hacer el programa siguiente. El método calcula_area puede recibir objetos de cualquier clase, siempre que

éstas desciendan de figura. (..)public class ppal {

Page 12: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-11

public static float calcula_area(figura f){ return f.calculaArea(); }public static void main(String[] args){

rectangulo r = new rectangulo(5,6);circulo c = new circulo(7);System.out.println(calcula_area(c));System.out.println(calcula_area(r));

}}

2.2.3.2 Ligadura Dinámica

Un mensaje es una petición enviada por un objeto a otro objeto para que active un método. El

nombre del objeto que envía el mensaje no aparece en el mismo. Realmente no son los objetos los que

envían mensajes a otros objetos, sino que los mensajes se originan en un método, que es la parte activa del

objeto.

Al proceso de seleccionar el método apropiado en base al tipo de objeto se llama ligadura. Si esta

puede aplazarse hasta el tiempo de ejecución, la selección se llama ligadura dinámica. Es decir, si todos

los objetos son asociados estáticamente a una clase, y no se tiene en cuenta los posibles cambios de

referencia, el método a aplicar puede determinarse en tiempo de compilación, sin que el sistema sufra

ningún tipo de sobrecarga. Sin embargo, en la mayoría de los casos, es interesante que los cambios de

referencia producidos en tiempo de ejecución influyan en el cómputo.

La ligadura estática significa que se fijan los tipos de todas las variables y expresiones en tiempo

de compilación; la ligadura dinámica (también llamada ligadura tardía) significa que los tipos de las

variables y expresiones no se conocen hasta el tiempo de ejecución.

La ligadura dinámica es la capacidad de retrasar hasta el instante de la recepción del mensaje la

decisión sobre la clase del objeto que lo recibe y el método concreto que debe de ejecutarse. Ejemplo: Supongamos un programa en Java como el de la sección “Polimorfismo”. Ahora, en lugar de crear dos objetos,

crearemos un objeto rectángulo o círculo según el usuario introduzca una opción del menú. En tiempo de

compilación es imposible saber la clase del objeto al que apunta la referencia f de la clase figura. Por tanto, es

imposible hasta el momento de la ejecución que método de calcularArea se va a activar sobre el mismo. public class ppal {

public static float calcula_area(figura f){ return f.calculaArea(); }public static void main(String[] args){

figura f; // referencia a figuraint opcion;

// Presentar menú// Pedir una opción al usuario// Almacenar la opción en “opcion”if (opcion==1)

f = new rectángulo(6,7);else

f = new circulo(8);System.out.println(f.calculaArea());

}}

3 Lenguajes Orientados a Objetos.

3.1 Orígenes de los lenguajes orientados a objetos

Una de las opiniones más difundidas hoy en día se basa en considerar la orientación a objetos como una evolución natural de distintos aspectos, como el ocultamiento de la información o la descomposición modular. Algunos lenguajes de programación han contribuido a la evolución de los lenguajes orientados a objetos:

� LISP, en los años 50, es un lenguaje de Inteligencia Artificial que introdujo el concepto de ligadura dinámica y la ventaja de un entorno de desarrollo interactivo.

� SIMULA-67, derivado de ALGOL-60, incorporó los conceptos de: ♦ Encapsulación y objetos ♦ Verificación estática de tipos

Page 13: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-12

♦ Clases (como patrones de objetos) ♦ Los mecanismos de herencia. ♦ El polimorfismo Posteriormente en lenguajes como Ada y Modula-2 se desarrolló la abstracción de datos.

� Pero sin duda alguna el lenguaje que ha contribuido enormemente al impulso del paradigma de la orientación a objetos ha sido SMALLTALK (basado en SIMULA), proyectado inicialmente en el Centro de Investigación Xerox de Palo Alto a principios de los 70, evolucionando a través de varios lanzamientos realizados por PARC y culminando con el producto Smalltalk-80 en el 81.

El empuje definitivo vino de la mano de extensiones orientadas a objetos para lenguajes tradicionalmente muy implantados como son PASCAL Y C.

3.2 Clasificación

Existen varias clasificaciones de los lenguajes de OOP: 1ª CLASIFICACIÓN: � PUROS: Un lenguaje orientado a objetos es puro si no permite salirse de la orientación a

objetos para realizar programación clásica. En él no existen datos que no formen parte de objetos y no hay otra forma de manejarlos mas que a través de mensajes. Este grupo incluye CLOS, SMALLTALK, ACTOR, EIFFEL, SIMULA. Son lenguajes potentes y flexibles pero lentos

� HÍBRIDOS: Un lenguaje es híbrido si permite programación clásica saliéndose del paradigma de la orientación a objetos. En estos lenguajes se complementa la programación clásica con la programación orientada a objetos y esta es posible gracias a extensiones semánticas del lenguaje. Sus principales ejemplos son: C++, OBJETIVE-C, OBJECT ORIENTED COBOL, OBJECT PASCAL, TURBO PASCAL, VISUAL OBJECT, DELPHI, JAVA. En general los lenguajes puros resaltan la exploración y el prototipado rápido y los híbridos ponen énfasis en la velocidad de ejecución. Ambos tipos suelen basarse en potentes librerías de clases y herramientas de desarrollo. Aunque pierden algunas características propias de la orientación a objetos, son más rápidos.

� SIMILARES: Además de los lenguajes orientados a objetos existen los lenguajes similares a objetos, como HYPERCAR de Apple Computer, que sirven para acercar a los programadores al paradigma orientado a objetos.

2ª CLASIFICACIÓN: Según su grado de orientación a objetos se dividen en: � BASADOS EN OBJETOS: su sintaxis y semántica soportan la creación de objetos (ADA-

83, ACTOR, VISUAL BASIC 4.0). Soporta el encapsulamiento y la identidad de objetos; es decir, los métodos y atributos se ocultan dentro y se hacen privados para los objetos, y estos objetos tienen identificadores únicos.

� BASADOS EN CLASES: incluyen el concepto de clases (abstracción) de objetos, además de soportar la funcionalidad de los objetos (CLU)

� ORIENTADOS A OBJETOS: soportan la funcionalidad de los objetos, su manipulación mediante clases y el manejo de éstas mediante herencia (SIMULA, C++, EIFFEL, SMALLTALK, TURBO PASCAL, DELPHI, OO COBOL, JAVA)

Además de las características de funcionalidad de los objetos, definición de clases y herencia, los lenguajes orientados a objetos deben tener (algunas o todas) las siguientes características:

� ENCAPSULACIÓN � COMPROBACIÓN DE TIPOS (CLASES): Un LOO puede tener comprobación estricta de

tipos, comprobación débil de tipos, o incluso no tener tipos. Comprobación estricta quiere decir que la concordancia se impone de manera estricta: no puede llamarse a una operación sobre un objeto a menos que en la clase o superclases del objeto esté definida la plantilla de esa operación. Los lenguajes con comprobación débil de tipos tienden hacia la comprobación estricta, pero es posible ignorar o suprimir las reglas sobre tipos. En un lenguaje sin tipos se puede enviar cualquier mensaje a cualquier clase (aunque ésta desconozca cómo responder al

Page 14: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-13

mensaje). � COMPILACIÓN INCREMENTAL (por partes) � GENERICIDAD (reusabilidad, posibilidad de definir módulos parametrizados. Ej: una lista es

un tipo genérico; puede ser una lista de nombres, de enteros o de algo específico, como nombre de empleados)

� PASO DE MENSAJES ENTRE OBJETOS � POLIMORFISMO � RECOLECCIÓN DE BASURA:

• Cuando se utiliza asignación estática de memoria, la liberación de ésta se produce cuando se completa la ejecución del programa. (Variables Globales).

• Cuando se utiliza asignación dinámica de memoria la liberación se produce cuando se completa la ejecución de un bloque (Variables Locales).

• Con los métodos de asignación de memoria heap controlados explícitamente: hay dos posibilidades, que el programador indica exactamente cuando se libera. O que el sistema implemente un recolector de basura (garbage collection).

� MANEJO DE EXCEPCIONES � CONCURRENCIA: En muchas ocasiones, un sistema automatizado puede tener que manejar

muchos eventos diferentes simultáneamente. En este caso, es habitual la utilización de procesadores capaces de realizar multitarea. Un solo proceso – llamado hilo (thread) de

control- es la raíz a partir de la cual se producen acciones dinámicas independientes dentro del sistema. Todo programa tiene al menos un hilo de control, pero un sistema que admita concurrencia puede tener muchos de tales hilos (multithread): algunos son transitorios, y otros permanecen durante todo el ciclo de vida de la ejecución del sistema. Los sistemas con múltiples CPUs permiten hilos de control verdaderamente concurrentes, mientras que los sistemas que se ejecutan en una sola CPU se limitan a conseguir hilos concurrentes de control mediante algún algoritmo de tiempo compartido.

� PERSISTENCIA: La persistencia es la propiedad de un objeto por la que su existencia trasciende el tiempo (es decir, el objeto continúa existiendo después de que su creador deja de existir) y/o el espacio (es decir, la posición del objeto varía con respecto al espacio de direcciones en el que fue creado).

3.3 Ventajas e inconvenientes.

Las principales VENTAJAS de programar mediante orientación a objetos son:

� Un lenguaje de programación que soporta el paradigma OO proporciona al desarrollador de

software una forma natural de modelar el mundo real, utilizando para ello clases de objetos.

� Los objetos bien diseñados en los sistemas OO constituyen la base para otros sistemas que se

ensamblan, en gran parte, a partir de módulos reutilizables, lo que redunda en una mayor

productividad. Esta es, quizás, la ventaja más conocida de la tecnología de objetos.

� La reutilización de clases existentes, que han sido probadas en proyectos anteriores, conduce a la

elaboración de sistemas de mayor calidad, que satisfacen mejor los requisitos de negocios y

contienen menos errores. El trabajo de programación es más fácil en base al uso de bibliotecas de

clases predefinidas.

� La POO, y la herencia en particular, hacen que sea posible utilizar y definir de forma clara

módulos funcionalmente incompletos y, luego, permiten su extensión sin trastornar la operación

de otros módulos o de sus clientes. Esto hace que los sistemas sean más flexibles, más fácilmente

extensibles y de mantenimiento menos costoso.

� La convención de paso de mensajes para la comunicación entre objetos lleva a que las

descripciones de la interfaz entre módulos y sistemas externos se haga más fácil. También facilita

la descripción y la construcción de Interfaces Gráficas de Usuario.

� El ocultamiento de información contribuye a construir sistemas seguros.

Los posibles INCONVENIENTES son:

� Un programa orientado a objetos se ejecuta más despacio sobre todo debido a la ligadura

Page 15: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-14

dinámica y al polimorfismo.

� El desarrollador de software tiene que conocer las bibliotecas de clases para sacar rendimiento al

lenguaje.

3.4 Principales lenguajes orientados a objetos

3.4.1 Simula

Simula, que anteriormente se denominaba Simula 67 fue, probablemente, el primer lenguaje que

presentó las nociones de clase y herencia jerárquica. No se admite la herencia múltiple. El ocultamiento de

información se lleva a cabo “protegiendo” una característica, lo cual, a su vez, evita que sea heredada en lo

sucesivo. Se admite el polimorfismo en forma de sobrecarga.

La comprobación de tipos se puede realizar, bien estáticamente en el momento de la compilación,

para mayor eficiencia, o bien en el momento de la ejecución si se define una característica como “virtual”.

El sistema necesita llevar a cabo la recolección de basura de vez en cuando, es decir, necesita

reutilizar la memoria que fue ocupada por instancias asignadas anteriormente, pero que ya no se están

utilizando.

Hace más énfasis en los procesos que en los datos, pero Simula es responsable de muchas de las

ideas que informaron a sus descendientes, sobre todo la idea de clases, instancias y herencia. Las idea de

abstracción está implícita, pero las nociones, como el paso de mensajes, tuvieron que esperar la llegada de

Smalltalk.

En resumen, las características de Simula son:

Comprobación de tipos /ligadura Temprana o tardía

Polimorfismo Sí

Ocultamiento de la información Sí

Concurrencia Sí

Herencia Sí

Herencia múltiple No

Recolección de basura Sí

Persistencia No

Genericidad No

Bibliotecas de objetos Simulación

3.4.2 Smalltalk

Es el lenguaje considerado como la representación más pura del ideal orientado a objetos. De

hecho, Smalltalk no es solamente un lenguaje, sino todo un entorno completo de programación, que

incluye numerosas librerías de clases, contemplándose las abstracciones básicas como colecciones o

diccionarios, así como clases gráficas para el manejo de ventanas, barras de desplazamiento, etc. Además

es un lenguaje casi imposible de separar de su entorno de desarrollo.

Originó gran parte de las definiciones de los conceptos básicos orientados a objetos de hoy en día:

objeto, clase, método, mensaje, herencia.

Influenciados por Simula, sus diseñadores tomaron la noción de objeto llevándola hasta el extremo,

y declararon que todo debería ser un objeto. Así, no existe otra forma de manejar datos que a través de

objetos y mediante el envío de mensajes. Incluso las clases son consideradas como objetos. Para mantener

la coherencia interna de la implementación se introduce el concepto de metaclase. (a cada clase le

corresponde un objeto virtual que es su metaclase, del que la clase es un caso particular). El único

concepto que no contempla es la herencia múltiple.

Necesita recolección de basura, y utiliza en su máximo grado la ligadura dinámica, permitiendo al

usuario enviar cualquier mensaje a cualquier objeto.

Smalltalk es un lenguaje sin tipos, no existen declaraciones de tipo de variables y no se realiza

ninguna comprobación estricta de tipos. De este modo los errores, que surgen cuando un objeto recibe un

Page 16: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-15

mensaje que no pueda resolver, por ejemplo, se procesan en su totalidad en el momento de la ejecución.

Como aspecto algo especial, las propiedades en Smalltalk pueden ser de dos tipos:

� privadas, que sólo conocen el propio objeto y sus métodos

� públicas, o de acceso permitido desde otros objetos.

Las características de Smalltalk podrían, entonces, resumirse así:

Comprobación de tipos /ligadura Tardía

Polimorfismo Sí

Ocultamiento de la información Sí

Concurrencia Escasa

Herencia Sí

Herencia múltiple No

Recolección de basura Sí

Persistencia No

Genericidad No

Bibliotecas de objetos Gráficas en su mayoría

VENTAJAS

� Smalltalk es un “lenguaje puro” orientado a objetos

� Excelente entorno de ejecución, que contiene depuradores, visores y un completo acceso a la

jerarquía de clases.

� La ligadura dinámica soporta el polimorfismo y, por tanto, una gran flexibilidad.

� La implementación a través de un intérprete facilita la labor de desarrollo de programas. Las

clases son añadidas, corregidas y depuradas de forma iterativa.

� Tiene una sintaxis simple, donde las variables y los atributos no necesitan tener un tipo

asociado. Es muy uniforme pues todo está definido en principio como objeto, incluyendo las

propias clases

DESVENTAJAS

� Es un lenguaje interpretado, lo que reduce su rendimiento y dificulta su comercialización

� Al proporcionar su propio entorno operativo, interactúa mal con otro tipo de software o

hardware.

� Los errores por paso de mensajes solo se pueden detectar en tiempo de ejecución.

3.4.3 Objective-C

Es un lenguaje híbrido diseñado para conjugar construcciones de objetos inspiradas en Smalltalk

con la potencia del C.

Soporta los mecanismos básicos de la orientación a objetos tales como objeto, clase, método y

mensaje, subclase y herencia. No se admite la herencia múltiple, pero ésta puede ser construida por el

programador.

Las extensiones semánticas que incorpora al C son básicamente la definición de clase (class), un

nuevo tipo de datos (el identificador de objetos), y una nueva operación (el paso de mensajes).

En este lenguaje cada definición de clase consta de dos archivos, uno de interfaz y otro de

implementación. El primero define lo que está disponible para los usuarios de la clase: su nombre, el

nombre de su clase padre, la declaración de las variables modelo (propiedades propias de cada objeto) y de

los métodos para los objetos de la clase. El segundo contiene la implementación real de los métodos.

Los mensajes se encierran entre corchetes con el objeto receptor en primer lugar y a continuación

el método.

Al igual que C++, soporta dos categorías de variables de instancia, privadas y públicas, por defecto

todas son privadas, es decir accesibles solo a través de los métodos de la clase.

Page 17: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-16

Objetive-C posee dos características importantes, su transportabilidad (a nivel de código objeto) y

su disponibilidad en una amplia gama de computadores, dado que el compilador acepta código fuente en

Objetive-C y genera una salida en código fuente C (que cuenta con compiladores en casi todas las

plataformas), que puede ser compilado para ejecutarlo en una máquina destino concreta.

Sus características se pueden resumir así:

Comprobación de tipos /ligadura Temprana o tardía

Polimorfismo Sí

Ocultamiento de la información Sí

Concurrencia Escasa

Herencia Sí

Herencia múltiple No

Recolección de basura Sí

Persistencia No

Genericidad No

Bibliotecas de objetos Unas pocas

3.4.4 C++

Es un lenguaje desarrollado en los laboratorios Bell por Bjarne Stroustrup, basándose en el

lenguaje C. Más tarde, su control directo pasó a manos de la agencia de estándares ANSI, en concordancia

con la ISO.

Se centra sobre todo en la eficiencia, diseñar código eficaz y proporcionar, por tanto,

características que permitan la manipulación del hardware y de la memoria a bajo nivel. Fue diseñado

desde el principio para ser realizado como un compilador de código fuente más que como un interprete de

código intermedio. El código generado por C++ es tan eficiente como el de C, salvo en el tema de las

llamadas virtuales a funciones.

C++ puede considerarse un lenguaje multiparadigma en el que el programador puede escoger el

estilo de la programación y establecer las características del lenguaje para satisfacer el problema.

Soporta los conceptos básicos de la orientación a objetos: objeto, clase, método, mensaje, subclase

y herencia, incluso herencia múltiple. Cada uno de los componentes de una clase se denominan miembro

(member). Los atributos se llaman miembros de datos (data-members) y los métodos miembros

funcionales (function-members).

Se introduce el concepto de niveles de acceso. El acceso a cada uno de los miembros de una clase,

atributos o métodos, puede pertenecer a uno de los siguientes niveles:

� Público, se puede utilizar en cualquier lugar donde se tenga acceso a la clase.

� Privado, sólo se puede utilizar en métodos declarados dentro de la misma clase.

� Protegido, se puede utilizar en métodos declarados dentro de la misma clase y en métodos de

clases descendientes de ella.

Las clases en C++ suelen disponer de dos tipos de métodos especiales, los llamados constructores

y los destructores, para crear o destruir respectivamente objetos de la clase. Además una clase puede

contener constructores de sobrecarga de operador.

C++ proporciona además mecanismos para implementar la ligadura dinámica, basados en la

definición de métodos virtuales dentro de una jerarquía de herencia. La forma de proceder consiste en

especificar un método como virtual en una clase padre. Redefiniendo después en una o más subclases, el

compilador especificará que cualquier mensaje a este método este dinámicamente ligado durante la

compilación, lo que garantiza que en la ejecución se escoja por lo menos un método de los definidos.

El programador puede optar por escoger ligadura estática o dinámica en determinadas partes del

programa, a diferencia de Smalltalk donde cualquier mensaje se puede enviar a cualquier objeto sin la

garantía de que esté definido para él.

C++ carece de recolección automática de basura. Tal característica debería ser construida por el

programador, o debería proporcionarla un entorno con bibliotecas de código adecuadas.

Page 18: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-17

Además, desde la aprobación de su estándar en 1998, C++ incorpora unas bibliotecas de

estructuras de datos como vectores, listas, pilas ... etc en su librería.

Las características de C++ se resumen así:

Comprobación de tipos /ligadura Temprana o tardía

Polimorfismo Sí

Ocultamiento de la información Sí

Concurrencia Escasa

Herencia Sí

Herencia múltiple Sí

Recolección de basura No

Persistencia No

Genericidad Sí (plantillas)

Bibliotecas de objetos Unas pocas

3.4.5 Ada

Es un lenguaje basado en objetos. Fue desarrollado a petición del Departamento de Defensa de

EEUU.

No permite que los objetos sean pasados como parámetros, lo que significa que no admite por

completo la abstracción de datos. Sin embargo, sí que admite la sobrecarga de operadores y proporciona la

recolección de basura como opción.

Ada no ofrece apoyo directo para la herencia, pero es posible utilizar paquetes genéricos para

construirla de forma limitada. Aun cuando es posible definir subtipos y tipos derivados, no es capaz

tampoco de extender los tipos existentes añadiendo nuevos métodos y atributos. Esto da lugar a la

necesidad de duplicar código.

No admite ligadura dinámica y hace una comprobación estricta de tipos, a efectos de mayor

eficiencia y seguridad.

Sus características generales son, por tanto:

Comprobación de tipos /ligadura Temprana

Polimorfismo Sí

Ocultamiento de la información Sí

Concurrencia Difícil

Herencia No

Herencia múltiple No

Recolección de basura No

Persistencia No

Genericidad Sí

Bibliotecas de objetos Unas pocas

3.4.6 Object-Oriented Pascal.

Al igual que C++, es un lenguaje híbrido, basado en extensiones semánticas de PASCAL. Los

objetos son registros de Pascal que encapsulan procedimientos y funciones. Solo admite herencia simple y

ofrece la recolección de basura como característica incorporada.

Sus características se resumen en el siguiente cuadro:

Comprobación de tipos /ligadura Tardía

Polimorfismo Sí

Ocultamiento de la información Sí

Concurrencia No

Herencia Basada en clases

Herencia múltiple No

Recolección de basura Sí

Page 19: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-18

Persistencia No

Genericidad No

Bibliotecas de objetos Unas pocas

3.4.7 Turbo Pascal

Es una extensión de Pascal realizada por Borland Intl. (ahora Inprise) con la mayoría de las

características orientadas a objetos. Las diferentes versiones soportan los mecanismos fundamentales de la

orientación a objetos: objeto, clase, métodos, mensajes y polimorfismo y herencia. Turbo Pascal incluye

capacidades derivadas de C++ como los métodos estáticos o virtuales, y constructores y destructores. Sin

embargo, ninguna versión soporta actualmente la herencia múltiple. Es muy popular debido a la enorme

popularidad que tuvo este producto de Borland.

Una posibilidad útil que incorporan la mayoría de las versiones es la de almacenar clases en

archivos separados, llamados unidades (tomadas de Modula-2), con secciones a su vez públicas y privadas,

las cuales pueden ser compiladas por separado y constituir verdaderas librerías de clases.

Comprobación de tipos /ligadura Temprana o tardía

Polimorfismo Sí

Ocultamiento de la información Sí

Concurrencia No

Herencia Sí

Herencia múltiple No

Recolección de basura No

Persistencia No

Genericidad No

Bibliotecas de objetos Unas pocas

3.4.8 Eiffel

Es un lenguaje orientado a objetos, escrito específicamente, y que intenta tratar a conciencia los

temas de corrección, robustez, transportabilidad y eficiencia. A diferencia de Smalltalk y Objective-C, en

Eiffel las clases no son objetos. Esto hace posible utilizar tipos estáticos que ayuden a eliminar los errores

en el momento de la ejecución y, también, ayuda a mejorar la eficiencia.

Las clases describen la realización de los tipos abstractos de datos. Se definen en el momento de la

compilación, y pueden crear instancias del tipo (objetos) en el momento de la ejecución.

Una de sus ventajas la constituye la robustez de sus herramientas de desarrollo, tipado completo y

herencia múltiple. Esta última es soportada con funciones del lenguaje que resuelven conflictos de

nombres. Cuando una clase hereda de dos padres que tienen variables de instancia con el mismo nombre, el

programador puede cambiar el nombre de una de las variables de instancia, de forma que ambas variables

puedan utilizarse sin conflicto en la subclase. Además de resolver conflictos entre nombres, el cambio de

nombre puede utilizarse para proporcionar un conjunto más adecuado y consistente de nombres para los

servicios que ofrece una clase.

Eiffel tiene comprobación de tipos durante la compilación, garantizando que en la ejecución ningún

mensaje se envíe a un objeto que no lo reconozca y si hay varios métodos con el mismo nombre se escoja

el adecuado.

Para aumentar su utilidad incluye un mecanismo de tratamiento de excepciones. A una rutina

pueden añadírsele “afirmaciones” que expresen condiciones previas (pre-condiciones) o condiciones

posteriores (post-condiciones). Las afirmaciones se heredan de la misma forma que se heredan los métodos

y pueden ser activadas o desactivadas con opciones de compilación. Cuando ocurre una excepción durante

la ejecución de una rutina, como violar una pre-condición o una post-condición, se llama automáticamente

a la cláusula de rescate de la rutina que será la encargada de limpiar el entorno o terminar o de cambiar las

condiciones y ejecutar de nuevo la rutina.

Admite herencia. Se pueden especificar condiciones previas y posteriores para crear módulos

seguros. Se admite la herencia múltiple, pero los conflictos de herencia no se resuelven, porque los

Page 20: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-19

métodos o los atributos heredados de los antecesores deben cambiar de nombre en el descendiente.

Eiffel dispone de un mecanismo para la recolección automática de basura, que libera el espacio

ocupado por objetos no necesarios para la aplicación. Su entorno de desarrollo incluye bibliotecas de

clases, visor de clases, editor integrado y herramientas de gestión de la configuración.

Las características de Eiffel se pueden resumir así:

Comprobación de tipos /ligadura Temprana

Polimorfismo Sí

Ocultamiento de la información Sí

Concurrencia No

Herencia Sí

Herencia múltiple Sí

Recolección de basura Sí

Persistencia Algo

Genericidad Sí

Bibliotecas de objetos Unas pocas

VENTAJAS

� Es un lenguaje orientado a objetos “puro”

� Es un lenguaje orientado al diseño de grandes aplicaciones. Las propiedades vistas le hacen

ideal para el diseño de aplicaciones en grupos de trabajo

� Su compatibilidad con C asegura su portabilidad hacia otros sistemas operativos.

INCONVENIENTES

� El manejo de la memoria, un punto delicado en todos los lenguajes orientados a objetos, no es

transparente como en el caso de Smalltalk.

� Las librerías de clases son reducidas.

� El rendimiento es mayor que el de Smalltalk, pero al tener que incluir un módulo run-time

dentro del ejecutable, su tamaño crece y su rendimiento baja.

3.4.9 Java

Java es un lenguaje de programación orientado a objetos desarrollado por la compañía Sun

Microsystems. Basado en C++, el lenguaje Java se diseñó para ser pequeño, sencillo y portable a diferentes

plataformas y sistemas operativos.

El rápido crecimiento de Internet y el deseo de los programadores por hacer dinámicas las páginas

HTML ha hecho que Java se haya convertido en un medio potente y popular de crear aplicaciones en

Internet.

Java permite crear páginas en Internet funcionales, dinámicas y en general más interesantes que las

creadas con la utilización del lenguaje HTML. Java también permite la creación de aplicaciones

totalmente funcionales, de la misma forma que otros programas como C / C++, Pascal, etc.

Debajo de toda esa innovación que supuso la aparición de Java, se esconde una compleja

tecnología basada en una máquina virtual y sistema de seguridad.

3.4.9.1 Un poco de historia

Java se creó con la intención de desarrollar un lenguaje que fuera independiente del sistema o

plataforma informática en el que se utilizase. En un principio se pensó como lenguaje de programación

para desarrollar software de aparatos electrónicos como tostadoras u hornos microondas y,

fundamentalmente, televisión interactiva. El software de estos tipos de aparatos debería poder funcionar

con nuevos procesadores que se fueran desarrollando. Otros requisitos importantes eran la fiabilidad del

código y la facilidad de desarrollo.

Los lenguajes convencionales como C o C++ no sirven para esta función, pues son dependientes

del sistema lo que provoca que cada programa tenga que compilarse para cada procesador diferente.

Uno de los miembros del equipo de Sun que trabajaba en estos problemas, James Gosling, había

estado trabajando anteriormente en su tiempo libre en un lenguaje de programación que él había llamado

Page 21: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-20

Oak, según parece el nombre se debe al roble que se veía por la ventana de su casa, que, partiendo de C++,

intentaba mejorar su eficiencia. Oak era un lenguaje bastante sencillo, fiable e independiente de la

arquitectura, por lo que Gosling decidió mejorar sus características y utilizarlo.

En 1993, cuando se seguía trabajando en este lenguaje, apareció el boom de Internet. El equipo

que desarrollaba Oak pensó que un lenguaje independiente de la arquitectura sería lo ideal para programar

en Internet, ya que los programas podrían funcionar en cualquier clase de ordenador que estuviese

conectado a la red. Tras un cambio de nombre y algunos de diseño, el lenguaje Java fue presentado en

sociedad en agosto de 1995.

Las características del lenguaje Java como fiabilidad (desarrollo de aplicaciones robustas) y

portabilidad (desarrollo de programas multiplataforma) son idóneas para el desarrollo de aplicaciones

basadas en la Web debido a la inherente heterogeneidad de las máquinas que están conectadas a Internet,

lo que permite la ejecución fiable y segura de las aplicaciones desarrolladas sin tener en cuenta la

plataforma en la que se va a ejecutar.

Este conjunto de características ha llevado a convertir a Java en uno de los lenguajes más utilizados

para el desarrollo de aplicaciones Web.

3.4.9.2 Características

Las características que posee Java respecto a otros lenguajes de programación son:

3.4.9.2.1 Simple

Java ofrece toda la funcionalidad de un lenguaje potente, pero sin las características menos usadas

y más confusas de éstos. C++ es un lenguaje que adolece de falta de seguridad, pero C y C++ son

lenguajes más difundidos, por ello Java se diseñó para ser parecido a C++ y así facilitar un rápido y fácil

aprendizaje.

Java elimina muchas de las características de otros lenguajes como C++, para mantener reducidas

las especificaciones del lenguaje y añadir características muy útiles como el garbage collector (recolector

de basura). No es necesario preocuparse de liberar memoria, el recolector se encarga de ello y como es un

thread de baja prioridad, cuando entra en acción, permite liberar bloques de memoria muy grandes, lo que

reduce la fragmentación de la memoria.

Java reduce en un 50% los errores más comunes de programación con lenguajes como C y C++ al

eliminar muchas de las características de éstos, entre las que destacan:

• aritmética de punteros

• no existen referencias

• registros (struct)

• definición de tipos (typedef)

• macros (#define)

• necesidad de liberar memoria (free)

Los arrays y strings son objetos.

3.4.9.2.2 Orientado a Objetos

Desde su diseño, Java es concebido como un lenguaje de programación orientado a objetos. Esto

se debe a la facilidad conceptual y de mantenimiento que provee esta visión del sistema (no como la

estructurada que, concibe la realidad desde otro punto de vista no tan natural como el de objetos,

dificultando el mantenimiento), y a la buena integración entre el paradigma orientado a objetos y los

objetivos iniciales del lenguaje Java, como programación distribuida y cliente/servidor.

Al ser Java orientado a objetos, éste hereda todas o casi todas las ventajas (y desventajas) de este

paradigma, principalmente en lo que respecta a la ingeniería del software. De esta manera, se “facilita” la

tarea de análisis y diseño del sistema, obteniendo al final de un modelo más claro y manejable. Además el

desarrollo y mantenimiento es más rápido y “fácil”, lo que permite abaratar costes de desarrollo,

implementación y mantenimiento final.

Java trabaja con sus datos como objetos y con interfaces a esos objetos. Soporta las características

Page 22: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-21

propias del paradigma orientado a objetos: encapsulación1, polimorfismo

2 y herencia

4. Las plantillas de

objetos son llamadas clases y sus copias, instancias de objetos. Estas instancias necesitan ser construidas

y destruidas en espacios de memoria.

Java incorpora funcionalidades como por ejemplo, la resolución dinámica de métodos. En C++ se

suele trabajar con librerías dinámicas (DLLs) que obligan a recompilar la aplicación cuando se retocan las

funciones que se encuentran en su interior. Este inconveniente es resuelto por Java mediante una interfaz

específica llamada RTTI (RunTime Type Identification) que define la interacción entre objetos excluyendo

variables de instancias o implementación de métodos. Las clases en Java tienen una representación en el

runtime que permite a los programadores interrogar por el tipo de clase y enlazar dinámicamente la clase

con el resultado de la búsqueda.

3.4.9.2.3 Distribuido

Java se ha construido con extensas capacidades de interconexión TCP/IP. Existen librerías de

rutinas para acceder e interactuar con protocolos como http y ftp. Esto permite a los programadores

acceder a la información a través de la red con tanta facilidad como a los ficheros locales.

Java en sí no es distribuido, sino que proporciona las librerías y herramientas para que los

programas puedan ser distribuidos, es decir, que corran en varias máquinas, interactuando.

Java fue diseñado con especial énfasis en el desarrollo de aplicaciones de red. Por ejemplo, la clase

URL permite que una aplicación acceda a objetos remotos en la red. Con Java es tan fácil abrir un fichero

remoto como uno real. También soporta conexiones de red a través de la clase Socket, que permite la

creación de servidores y clientes distribuidos.

3.4.9.2.4 Arquitectura Neutral y Portabilidad

Los programas compilados con Java se pueden utilizar en cualquier plataforma o máquina que

tenga implementado un intérprete de Java (portabilidad). Para ello, al compilar el código fuente se genera

byte-code independiente de cualquier plataforma física real, independiente de cualquier sistema operativo.

El compilador es diferente dependiendo de la plataforma en la que se trabaje, pero el producto final de la

compilación es el mismo.

El “Bytecode” se puede interpretar en cualquier plataforma, utilizando para ello un intérprete (run-

time) diseñado para la plataforma en cuestión, sin importar en modo alguno la máquina donde haya sido

generado, capaz de transformar este código en otro que entienda la máquina local. Esto se conoce como

Máquina Virtual Java “Java Virtual Machine” (Figura 1).

1 Encapsulación: Integración entre datos y métodos en una sola unidad. Además, propiedad que permite asegurar que están ocultas aquellas

partes que no sean esenciales del objeto. De esta manera, el objeto esconde sus datos de los demás objetos, y permite el acceso a los datos

mediante sus propios métodos.

2 Polimorfismo: Interfaz múltiple de métodos. Además, relativa a un solo método, significa que se permite que se aplique sobre varios tipos

de objetos.

4 Herencia: Mecanismo que permite compartir características (atributos) y comportamiento (métodos) entre clases, tomando como base una

relación jerárquica.

Page 23: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-22

Figura 1.- Máquina Virtual Java

3.4.9.2.5 Robusto

Uno de los objetivos principales en el diseño de Java es la robustez y fiabilidad de las aplicaciones

que se desarrollan utilizando este lenguaje de programación.

Java intenta que el código sea fiable, y para ello hace énfasis en el chequeo del byte-code para

detectar posibles problemas. Las verificaciones se realizan tanto en tiempo de compilación como en tiempo

de ejecución. En tiempo de compilación se realiza un severo y amplio chequeo de tipos, por lo que se

considera a Java un lenguaje fuertemente tipado. Esto, junto con la obligación de la declaración explícita

de métodos, permite encontrar un gran número de errores en una etapa temprana de la implementación.

Java elimina toda posibilidad de acceder directamente a posiciones físicas de memoria y de esta

manera se elimina la posible sobreescritura o corrupción de áreas de memoria que podrían estar reservadas

a otros fines. Al hilo de esto, implementa los arrays auténticos, en vez de listas enlazadas de punteros, con

comprobación de límites, evitando problemas que pueden ser muy graves. Estas características reducen

drásticamente el tiempo de desarrollo de aplicaciones en Java.

Java proporciona, pues:

• Comprobación de punteros

• Comprobación de límites de arrays

• Excepciones

• Verificación de byte-codes

También permite el manejo de excepciones, señales que indican que se ha producido una

determinada condición, como puede ser un error.

3.4.9.2.6 Interpretado

Java para conseguir ser un lenguaje independiente del sistema operativo y del procesador que

incorpore la máquina utilizada, es tanto interpretado como compilado.

El código fuente, escrito con cualquier editor de textos, se compila generando el byte-code. Este

código intermedio es de muy bajo nivel, pero sin alcanzar las instrucciones máquina propias de cada

plataforma. El byte-code corresponde a alrededor del 80% de las instrucciones de la aplicación. Ese mismo

código es el que se puede ejecutar sobre cualquier plataforma. Para ello hace falta el run-time, que sí es

completamente dependiente de la máquina y del sistema operativo, que interpreta dinámicamente el byte-

code y añade el 20% de instrucciones que faltaban para su ejecución.

Con este sistema es fácil crear aplicaciones multiplataforma, pero para ejecutarlas es necesario que

exista el run-time correspondiente al sistema operativo utilizado.

Page 24: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-23

3.4.9.2.7 Multithread

Java da soporte a la multiprogramación mediante la ejecución de múltiples actividades (threads)

simultáneas en un programa. Los threads (a veces llamados, procesos ligeros), son básicamente pequeños

procesos o piezas independientes de un gran proceso. Java soporta multithreading a nivel de lenguaje

mediante la incorporación de la clase “thread” .

Esta característica del lenguaje permite desarrollar aplicaciones que puedan realizar varias

operaciones de forma concurrente, como por ejemplo el navegador HotJava, desarrollado íntegramente en

Java, puede estar bajando un fichero de la red sin dejar de navegar y estar escuchando sonido que

incorpora alguna página HTML.

Los threads que define Java son “Pre-emptivos” (se les asigna un quantum de tiempo de

procesamiento) y dependen totalmente de la plataforma real sobre la que se esté ejecutando la Máquina

Virtual. De esta forma los threads pueden ser de tiempo compartido (time sliced), pero todo esto depende

del sistema operativo subyacente. En caso de que el sistema no de soporte de tiempo compartido, una vez

iniciado un thread la única manera de que deje el control del procesador es si toma el control otro thread

con mayor prioridad.

3.4.9.2.8 Dinámico

Java utiliza ligadura dinámica. La ligadura dinámica consiste en cargar las clases en tiempo de

ejecución, es decir, cuando se hace necesaria su utilización. Cuando una instrucción byte-code hace

referencia a un método concreto, la Máquina Virtual Java, en tiempo de ejecución, debe averiguar la

versión correcta del método que debe utilizar. Esto es debido a que ese método podría estar definido en el

propio programa o también puede haberse heredado de otra clase.

Java, durante la compilación no genera referencias numéricas determinadas, sino que obtiene una

referencia simbólica que le pasa al Verificador del Byte-Code y al Intérprete. Este último, invoca al

Sistema de Resolución de Nombres cuando las clases se comienzan a linkar. Una vez finalizada la

resolución de los nombres de los métodos, se reescribe la referencia como un offset numérico, obteniendo

en ese momento una referencia numérica directa.

Si el sistema ejecuta una aplicación Java sobre la red y encuentra una pieza de la aplicación que no

sabe manejar, Java es capaz de traer automáticamente cualquiera de esas piezas que el sistema necesita

para funcionar (Figura 2).

Para evitar tener que traer por la red los módulos de byte-codes o los objetos o nuevas clases cada

vez que se necesiten, Java implementa las opciones de persistencia para que no se eliminen cuando se

vacíe la caché de la máquina.

Figura 2.- Incorporación dinámica de clases en Java

3.4.9.2.9 Herencia

Java no soporta la herencia múltiple. La herencia múltiple es aquella en la que una clase se crea a

partir (hereda características y comportamiento) de varias clases, es decir que tiene varios “padres”. Esta

característica aporta potencia al lenguaje pero también provee varios problemas técnicos como la colisión

de nombres y la herencia repetida. La primera surge cuando una subclase hereda de diferentes superclases

Page 25: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-24

características iguales, y la segunda ocurre cuando una clase es subclase de otra por varios caminos.

Este tipo de herencia genera ambigüedad que se debería solucionar, y Java lo elimina de raíz ya que

no la permite, de forma que no complica el lenguaje.

Un motivo más para desechar la herencia múltiple es que los beneficios que ésta podría aportar son

provistos por medio de las interfaces Java, evitando los inconvenientes que se derivan de su uso. Una

interfaz, se utiliza para crear una clase base abstracta que contenga solamente las constantes y las

declaraciones de los métodos de la clase. No se permite que haya variables miembro ni definiciones de

métodos. Además, en Java también se pueden crear clases abstractas.

3.4.9.2.10 Ligadura

Java requiere que todas las variables de tipos primitivos sean instanciadas en tiempo de

compilación, y todos los objetos sean instanciados en memoria dinámica en tiempo de ejecución (ligadura

dinámica).

3.4.9.2.11 Constructores

Java soporta constructores que pueden ser sobrecargados. Si no se proporciona un constructor

explícitamente, el sistema proporciona un constructor por defecto.

No hay destructores en Java. La memoria que no se utiliza es devuelta al sistema a través del

recolector de basura, que se ejecuta en un thread diferente al del programa principal.

3.4.9.2.12 Niveles de acceso

En Java existen tres niveles de acceso:

� Público (public), puede ser accedido desde cualquier parte.

� Privado (private), sólo se puede utilizar en métodos declarados dentro de la misma clase, no se

heredan por las subclases y no son accesibles desde ellas.

� Protegido (protected), se puede utilizar en métodos declarados dentro de la misma clase, las subclases

y las otras clases definidas dentro del mismo paquete (agrupación de clases).

3.5 Elección de un lenguaje OO

1) LIGADURA DINÁMICA FRENTE A ESTÁTICA La ligadura dinámica es un mecanismo necesario para soportar el paradigma de la orientación a

objetos. Sin embargo, con ésta se disminuye el rendimiento, ya que se necesita una búsqueda en tiempo de

ejecución para hacer coincidir un método a cada mensaje. Además conduce a una gran cantidad de errores

de programación, errores que normalmente son detectados durante la compilación en lenguajes tipeados

estáticamente, pero que no se detectan hasta la ejecución en lenguajes con ligadura dinámica.

Una mezcla entre tipos estáticos y ligadura dinámica constituye una buena solución, ya que ofrece

un equilibrio entre flexibilidad de programación y eficiencia en la ejecución.

Pero incluso con tipos estáticos, algunas aplicaciones, como las de tiempo real, son tan críticas en

tiempo de ejecución que no pueden tolerar este tiempo adicional que conlleva la ligadura dinámica. Si se va

a utilizar un lenguaje OO para resolver este tipo de problemas, debe permitir descomponer el paradigma

orientado a objetos y programar en construcciones estáticas que no den lugar a retardos de ejecución, lo

que conlleva utilizar lenguajes híbridos que permitan esta separación de paradigmas.

A la hora de desarrollar software habrá que establecer un compromiso entre la limitación de

velocidad de los lenguajes OO frente a sus ventajas en tiempo de desarrollo, tamaño menor de código, fácil

modificación, etc.

2) CLASES COMO OBJETOS En la orientación a objetos se distingue claramente entre clases y objetos. Las clases son plantillas

estáticas que existen solamente en el cuerpo del código fuente de un programa y los objetos son entidades

dinámicas que existen en áreas de memoria durante la ejecución del programa. Pero existen dos corrientes:

� Los que consideran las clases como objetos, lo cual proporciona al paradigma una mayor consistencia

y simplicidad conceptual.

� Los que consideran aspectos separados, insistiendo en que las clases son descripciones de cosas y los

objetos son las cosas mismas.

Page 26: Programacion Orientada a Objetos.pdf

Capítulo 1: Programación orientada a objetos

1-25

La elección de un lenguaje que contemple una opción u otra depende de la aplicación. Para un

rápido prototipado y experimentación, los programadores escogen la mayor potencia y flexibilidad de un

lenguaje que considere las clases como objetos. Para el desarrollo de aplicaciones tradicionales se suele

escoger un lenguaje donde existe separación entre clases y objetos.

3) CONCURRENCIA El paradigma de la orientación a objetos parece útil para modelar la mayor parte de los procesos

del mundo real. Pero el paso de mensajes es sin duda alguna un proceso lineal, con lo que parece no muy

adecuado para modelar procesos concurrentes, donde el modelo parece derrumbarse.

En la resolución de sistemas concurrentes, puede parecer que los mensajes deberían pasarse

simultáneamente. Pero esto no es así y lo que se hace es establecer un orden lineal de sucesos que puede,

en el peor de los casos, desfigurar significativamente el proceso del mundo real que está siendo modelado.

Una técnica utilizada consiste en serializar dichos sucesos concurrentes utilizando semáforos, pero

esto solo se adaptaría a las situaciones en las que se tengan pocos procesos activos ya que puede dar lugar

a una gran carga de procesos en espera.

Una solución mejor para modelar sucesos concurrentes es no solo simular la concurrencia sino

proporcionar realmente un medio en el que los objetos puedan verdaderamente ejecutarse

simultáneamente. Esto requiere un hardware con arquitecturas paralelas y lenguajes paralelos que soporten

con garantías el modelo. Existen varios proyectos de investigación al respecto como ABCL/R y PROCOL.

Alternativamente se han desarrollado lenguajes distribuidos que soportan la concurrencia

permitiendo que los objetos de diferentes maquinas se comuniquen concurrentemente a través del envío y

recepción de mensajes. Es el caso de Smalltalk distribuido.