|
 |
 |
 |
 |
Publicaciones de Estudiantes
Francisco Javier Pabón Molina
Titulo: Principios de Programación II
Area: Information Systems
Pais:
Perfil:
Programa:
Available for Download:
Yes
Diseminar información, ideas innovadoras y
conocimientos académicos es una función
importante para Atlantic Internacional
University. Publicaremos noticias, artículos,
comentarios y otras publicaciones de
nuestros estudiantes y otros colaboradores.
Si desea contactar al autor por motivos
profesionales favor enviar su petición por
este medio.
|
|
| |
|
|
| |
1.
Introducción
En este ensayo titulado “Principles
of programming: Object Oriented
Programming”
pretendo dar un recorrido a este
paradigma de programación actual que
es
utilizado por miles de programadores
a nivel mundial, y que se ha
convertido en un
estándar en el desarrollo de
aplicaciones tanto de escritorio,
Web e Internet y
dispositivos móviles.
A lo largo del presente texto se ira
describiendo el origen, evolución,
tendencias
actuales y ciertos patrones de
diseño, así como una vista aunque no
muy profunda
si lo mas fiel posible a un lenguaje
de programación que ha revolucionado
el
presente y porque no decirlo también,
el futuro de la programación actual,
el
lenguaje Java.
¿Por qué Java?, en lo que va de mi
corta pero interesante carrera
profesional en
tecnologías de información he tenido
contacto con un pequeño numero de
lenguajes, desde Pascal (del cual
desarrollé el ensayo de Principles
of
programming I), donde se trató la
programación estructurada, dando una
minúscula exploración a Delphi,
lenguaje C y haciendo uso de
herramientas
propietarias en las cuales he tenido
mas experiencia y profundización
como ser la
suite Microsoft Visual Studio 6.0 en
el que comencé a dar mis primeros
pasos con
este estilo de programación de
objetos y el cual en la actualidad
sigo utilizando,
haciendo un cambio a la plataforma
.Net y lo que se ha aplica
actualmente el
concepto de framework1 de desarrollo,
existiendo varias tendencias o
estilos;
aunque las herramientas antes
mencionadas proveen de cierta
facilidad y
productividad al programador y
desarrollador de aplicaciones,
tienen la limitación
de la plataforma y ser propietarias2
y no en muchas universidades se
encuentran
disponible para la enseñanza, es
aquí donde entra Java.
Como se ira viendo, Java tiene la
ventaja de ser multiplataforma y
detallaré más a
fondo estas características en los
siguientes apartados, y si uno como
profesional
aplica para obtener un trabajo en el
área de la programación, es casi una
obligación desde un punto de vista
personal conocer y desempeñarse en
ambas
plataformas y certificarse3, para
ofrecer y brindarle mayores
soluciones a la
empresa, organización o individuo
que requiera de sus servicios.
También se pretende dar una pequeña
crítica a este estilo de
programación,
porque aunque todo tiene sus
ventajas y desventajas, y como dije
al principio, la
comunidad de desarrolladores es muy
amplia, hay muchos de los cuales aun
no
están del todo conformes y prefieren
todavía otros estilos y metodologías.
1 En desarrollo de software, un
framework es definido como una
estructura de apoyo en la cual otro
proyecto de software
puede ser organizado y desarrollado.
2 El uso de herramientas
propietarias, generalmente ligadas a
tecnologías específicas bajo el
control de determinadas
empresas, contribuye a lograr una
fuerte dependencia del futuro
profesional en las mismas.
3 Actualmente, certificarse es un
requisito en el mercado tecnológico.
La competencia es cada vez mayor y
debes estar
preparado para los cambios del
mercado.
Las prácticas y desarrollos se harán
con el JRE 5.0 Update 6 y como IDE
me he
decidido por Eclipse Project del
cual también detallaré mas adelante.
Agradecer a Atlantic International
University por brindarme la
oportunidad de poder
mostrar mis conocimientos y adquirir
y profundizar los nuevos que he
elegido en
vista a un mejor crecimiento
profesional.
2. Paradigma de la Programación
Un paradigma es una forma de
representar y manipular el
conocimiento.
Representa un enfoque particular o
filosofía para la construcción o
ingeniería de
software. No es mejor uno que otro
sino que cada uno tiene sus ventajas
y
desventajas. También hay situaciones
donde un paradigma es mejor que otro.
Un paradigma provee (y determina) la
vista que el programador tiene de la
ejecución del programa. Por ejemplo,
en un programa orientado a objetos,
los
programadores pueden pensar en un
programa como una colección de
interacción
de objetos, mientras en un programa
funcional un programa puede ser
pensado
como una secuencia de evaluaciones
de función sin estado.
Tal como diferentes grupos en
ingeniería de software abogan por
las diferentes
metodologías, los distintos
lenguajes de programación abogan por
los diferentes
paradigmas de programación. Algunos
lenguajes son diseñados para apoyar
un
paradigma particular (Smalltalk4 y
Java apoyan la programación
orientada a
objetos mientras Haskell5 y Scheme6
apoyan el paradigma de programación
funcional), otros lenguajes de
programación apoyan múltiples
paradigmas.
Algunos ejemplos de paradigmas de
programación:
El paradigma imperativo es
considerado el más común y está
representado, por
ejemplo, por el C7 o por BASIC8.
• El paradigma funcional está
representado por la familia de
lenguajes LISP9,
en particular Scheme.
• El paradigma lógico, un ejemplo es
PROLOG10.
Si bien puede seleccionarse la forma
pura de estos paradigmas al momento
de
programar, en la práctica es
habitual que se mezclen. Tal es el
caso de lenguajes
como C++, Delphi o Visual Basic, los
cuales combinan el paradigma
imperativo
con el orientado a objetos.
Por ejemplo, C++ es diseñado para
apoyar los elementos de programación
procedural, programación basada a
objetos, programación orientada a
objetos, y
programación genérica.
4-10 Lenguajes de programación
pertenecientes a distintos
paradigmas.
Uno puede escribir un programa
puramente procedural en C ++, puede
escribir un
Sin embargo, los diseñadores y
programadores deciden como construir
un
programa que usa aquellos elementos
de un paradigma. programa puramente
orientado a objetos en C ++, o puede
escribir un programa que contiene
los
elementos de ambos paradigmas.
En estos estilos es donde entra la
controversia por parte de muchos
programadores en cuanto a cual es
mejor o cumple sus necesidades, y
con la
evolución de los lenguajes, van
aplicándose nuevos paradigmas, por
ejemplo el de
programación orientada a aspectos,
el cual es reciente y su intención
es permitir
una adecuada modularización y
posibilitar una mejor separación de
conceptos.
Varias tecnologías con nombres
diferentes se encaminan a la
consecución de los
mismos objetivos y así, el término
POA (Programación Orientada a
Aspectos) es
usado para referirse a varias
tecnologías relacionadas.
Muchas veces nos encontramos, a la
hora de programar, con problemas que
no
podemos resolver de una manera
adecuada con las técnicas habituales
usadas en
la programación procedural o en la
programación orientada a objetos. O
que en
otro lenguaje se resuelven de forma
más sencilla y tratamos de evitar en
la
mayoría de las veces varias líneas
de código. Con éstas, nos vemos
forzados a
tomar decisiones de diseño que
repercuten de manera importante en
el desarrollo
de la aplicación y que nos alejan
con frecuencia de otras
posibilidades. Pero,
como se repite en este apartado,
todo tiene sus ventajas y se hará un
énfasis a la
programación orientada a objetos y
sus fortalezas.
Algunos diseñadores de lenguajes han
dado por sentado que la programación
orientada a objetos, de por sí, no
es adecuada para resolver de manera
sencilla
todos los problemas de programación,
y hacen referencia al uso de
lenguajes de
programación multiparadigma.
La descripción de los otros
paradigmas se dejara para un futuro
apartado.
3. Programación orientada a objetos
Aunque existen distintas
terminologías para nombrar los
mismos conceptos y
características importantes de la
programación orientada a objetos,
abreviada
POO, es importante entender la
mayoría de ellos tanto por quien la
desconoce
como por aquel que la conoce.
Las computadoras, más que máquinas,
pueden considerarse como
herramientas
que permiten ampliar la mente ("bicicletas
para la mente", como se enorgullece
de
decir Steve Jobs), además de un
medio de expresión inherentemente
diferente.
Como resultado, las herramientas
empiezan a parecerse menos a
máquinas y
más a partes de nuestra mente, al
igual que ocurre con otros medios de
expresión
como la escritura, la pintura, la
escultura, la animación o la
filmación de películas.
La programación orientada a objetos
(POO) es una parte de este
movimiento
dirigido a utilizar las computadoras
como si de un medio de expresión se
tratara.
La programación orientada a objetos
asevera dar mayor flexibilidad,
facilitando los
cambios a los programas y es
ampliamente popular en la gran
escala de
ingeniería de software. Además, los
que proponen la POO argumentan que
es
mas fácil de aprender para quienes
son nuevos en la programación de
computadoras y que su abordaje a
menudo es más fácil de desarrollar y
mantener
prestándose así mismo más análisis
directo, codificación y
entendimiento de
situaciones complejas y
procedimientos comparado a otros
métodos de
programación.
4. ¿Qué es la POO?
La programación orientada a objetos
es una evolución lógica de la
programación
estructurada, en la que el concepto
de variables locales a un
procedimiento o
función, que no son accesibles a
otros procedimientos y funciones, se
hace
extensible a los propios
subprogramas que acceden a estas
variables. Pero la
programación orientada a objetos va
mucho más allá. En realidad, cambia
la
concepción de la metodología de
diseño de los programas.
En la programación orientada a
objetos, se definen objetos que
conforman una
aplicación. Estos objetos están
formados por una serie de
características y
operaciones que se pueden realizar
sobre los mismos. Estos objetos no
están
aislados en la aplicación, sino que
se comunican entre ellos.
Los programadores que emplean
lenguajes procedurales, escriben
funciones y
después les pasan datos. Los
programadores que emplean lenguajes
orientados a
objetos definen objetos con datos y
métodos y después envían mensajes a
los
objetos diciendo que realicen esos
métodos en sí mismos.
4.1 Conceptos fundamentales
La programación orientada a objetos
hace énfasis en los siguientes
conceptos:
• Abstracción: Cada objeto en el
sistema sirve como modelo de un
"agente"
abstracto que puede realizar
trabajo, informar y cambiar su
estado, y
"comunicarse" con otros objetos en
el sistema sin revelar cómo se
implementan estas características.
Los procesos, las funciones o los
métodos pueden también ser
abstraídos y cuando los están, una
variedad
de técnicas son requeridas para
ampliar una abstracción. Es la
habilidad de
un programa de ignorar los detalles
de un objeto. Por ejemplo “Rin Tin
Tin”
el perro puede ser tratado como
perro la mayoría de las veces, menos
cuando es abstraído apropiadamente
al nivel de canido (superclase de
perro) o carnívoro (superclase de
canido) y así sucesivamente.
• Encapsulamiento: También llamada
"ocultación de la información", esto
asegura que los objetos no pueden
cambiar el estado interno de otros
objetos de maneras inesperadas;
solamente los propios métodos
internos
del objeto pueden acceder a su
estado. Cada tipo de objeto expone
una
interfaz a otros objetos que
especifica cómo otros objetos pueden
interactuar con él. Algunos
lenguajes relajan esto, permitiendo
un acceso
directo a los datos internos del
objeto de una manera controlada y
limitando
el grado de abstracción.
• Polimorfismo: Las referencias y
las colecciones de objetos pueden
contener objetos de diferentes
tipos, y la invocación de un
comportamiento
en una referencia producirá el
comportamiento correcto para el tipo
real del
objeto referenciado. Cuando esto
ocurre en "tiempo de ejecución",
esta
última característica se llama
asignación tardía o asignación
dinámica.
Algunos lenguajes proporcionan
medios más estáticos (en "tiempo de
compilación") de polimorfismo, tales
como las plantillas y la sobrecarga
de
operadores de C++.
• Herencia: Organiza y facilita el
polimorfismo y la encapsulación
permitiendo
a los objetos ser definidos y
creados como tipos especializados de
objetos
preexistentes. Estos pueden
compartir (y extender) su
comportamiento sin
tener que reimplementar su
comportamiento. Esto suele hacerse
habitualmente agrupando los objetos
en clases o Class y las clases en
árboles o enrejados que reflejan un
comportamiento común.
Cada uno de estos conceptos se irá
detallando más a fondo en los
siguientes
apartados.
4.2 ¿Qué es un Objeto?
La respuesta a esta pregunta en
términos ajenos a la programación
parece simple.
Un objeto es una persona, animal o
cosa. Se distingue de otros objetos
por tener
unas determinadas características y
“sirve” para algo, o dicho de otra
forma, se
pueden realizar distintas
operaciones con/sobre ese objeto.
Por ejemplo: Una casa es un objeto.
CARACTERÍSTICAS: Número de pisos,
altura total en metros, color de la
fachada, número de ventanas, número
de puertas, ciudad, calle y número
donde
está ubicada, etc.
OPERACIONES: Construir, destruir,
pintar fachada, modificar alguna de
las
características, como por ejemplo,
abrir una nueva ventana, etc.
Evidentemente, cada objeto puede
definirse en función de multitud de
características y se pueden realizar
innumerables operaciones sobre él.
Ya en
términos de programación, será
misión del programador determinar
qué
características y que operaciones
interesa mantener sobre un objeto.
Por ejemplo,
sobre el objeto casa puede no ser
necesario conocer su ubicación y por
lo tanto,
dichas características no formarán
parte del objeto definido por el
programador. Lo
mismo podría decirse sobre las
operaciones.
Pensar en términos de objetos es muy
parecido a cómo lo haríamos en la
vida
real. Por ejemplo vamos a pensar en
un coche para tratar de modelizarlo
en un
esquema de POO. Diríamos que el
coche es el elemento principal que
tiene una
serie de características, como
podrían ser el color, el modelo o la
marca. Además
tiene una serie de funcionalidades
asociadas, como pueden ser ponerse
en
marcha, parar o aparcar.
En terminología de programación
orientada a objetos, a las
características del
objeto se les denomina ATRIBUTOS y a
las operaciones MÉTODOS. Cada uno de
estos métodos es un procedimiento o
una función perteneciente a un
objeto.
Un objeto está formado por una serie
de características o datos
(atributos) y una
serie de operaciones (métodos). No
puede concebirse únicamente en
función de
los datos o de las operaciones sino
en su conjunto.
4.3 Abstracción
Todos los lenguajes de programación
proporcionan abstracciones. Puede
incluso
afirmarse que la complejidad de los
problemas a resolver es directamente
proporcional a la clase (tipo) y
calidad de las abstracciones a
utilizar, entendiendo
por tipo "clase", aquello que se
desea abstraer. El lenguaje
ensamblador es una
pequeña abstracción de la máquina
subyacente. Muchos de los lenguajes
denominados "imperativos"
desarrollados a continuación del
antes mencionado
ensamblador (como Fortran, BASIC y
C) eran abstracciones a su vez del
lenguaje
citado. Estos lenguajes supusieron
una gran mejora sobre el lenguaje
ensamblador, pero su abstracción
principal aún exigía pensar en
términos de la
estructura del computador más que en
la del problema en sí a resolver. El
programador que haga uso de estos
lenguajes debe establecer una
asociación
entre el modelo de la máquina
(dentro del "espacio de la
solución", que es donde
se modela el problema, por ejemplo,
un computador) y el modelo del
problema
que de hecho trata de resolver (en
el "espacio del problema", que es
donde de
hecho el problema existe).
La abstracción consiste en aislar un
elemento de su contexto o del resto
de los
elementos que lo acompañan. El
término se refiere al énfasis en el
"¿qué hace?"
más que en el "¿cómo lo hace?". El
común denominador en la evolución de
los
lenguajes de programación, desde los
clásicos o imperativos hasta los
orientados
a objetos, ha sido el nivel de
abstracción del que cada uno de
ellos hace uso.
Se sabe que los lenguajes de
programación son las herramientas
mediante las
cuales los diseñadores de lenguajes
pueden implementar los modelos
abstractos.
La abstracción ofrecida por los
lenguajes de programación se puede
dividir en dos
categorías: abstracción de datos
(pertenecientes a los datos) y
abstracción de
control (perteneciente a las
estructuras de control).
La abstracción encarada desde el
punto de vista de la programación
orientada a
objetos expresa las características
esenciales de un objeto, las mismas
distinguen
al objeto de los demás. Además de
distinguir entre los objetos provee
límites
conceptuales. Entonces se puede
decir que la encapsulación separa
las
características esenciales de las no
dentro de un objeto. Si un objeto
tiene mas
características de las necesarias
los mismos resultarán difíciles de
usar, modificar,
construir y comprender.
La misma genera una ilusión de
simplicidad dado a que minimiza la
cantidad de
características que definen a un
objeto.
Y todo es un objeto. Hay que pensar
en cualquier objeto como una
variable:
almacena datos, permite que se le
"hagan peticiones", pidiéndole que
desempeñe
por sí mismo determinadas
operaciones, etc. En teoría, puede
acogerse cualquier
componente conceptual del problema a
resolver (bien sean perros,
edificios,
servicios, etc.) y representarlos
como objetos dentro de un programa.
4.4 Métodos y mensajes
Un término que se utiliza más
frecuentemente en Java y POO es
método, al ser
"una manera de hacer algo". Si se
desea, es posible seguir pensando en
funciones. Verdaderamente sólo hay
una diferencia sintáctica, pero de
ahora en
adelante se usará el término
"método" en lugar del término
"función".
Los métodos son las operaciones que
pueden realizarse sobre el objeto,
que
normalmente estarán incorporados en
forma de programas (código) que el
objeto
es capaz de ejecutar y que también
pone a disposición de sus
descendientes a
través de la herencia.
Las partes fundamentales de un
método son su nombre, sus
parámetros, el tipo
de retorno y el cuerpo.
He aquí su forma básica:
tipoRetorno nombreMetodo ( /* lista
de parámetros */ ) {
/ * Cuerpo del método */
}
El tipo de retorno es el tipo del
valor que surge del método tras ser
invocado. La
lista de parámetros indica los tipos
y nombres de las informaciones que
es
necesario pasar a ese método. Cada
método se identifica unívocamente
mediante
el nombre del método y la lista de
parámetros.
En Java los métodos pueden crearse
como parte de una clase. Es posible
que un
método pueda ser invocado sólo por
un objeto2, y ese objeto debe ser
capaz de
llevar a cabo esa llamada al método.
Si se invoca erróneamente a un
método de
un objeto, se generará un error en
tiempo de compilación. Se invoca a
un método
de un objeto escribiendo el nombre
del objeto seguido de un punto y el
nombre del
método con su lista de argumentos,
como: nombreObjeto.nombreMetodo
(arg1,
arg2, arg3). Por ejemplo, si se
tiene un método f ( ) que no recibe
ningún
parámetro y devuelve un dato de tipo
int, y si se tiene un objeto a para
el que
puede invocarse a f ( ), es posible
escribir:
int x = a.f ();
El tipo del valor de retorno debe
ser compatible con el tipo de x.
Este acto de invocar a un método
suele denominarse envío de un
mensaje a un
objeto. En el ejemplo de arriba, el
mensaje es f ( ) y el objeto es a.
La
programación orientada a objetos
suele resumirse como un simple
"envío de
mensajes a objetos".
Un ejemplo claro sería el siguiente:
. Ejemplo de Clase Mamífero:
Datos Métodos
Color Desplazarse
Tamaño Masticar
Peso Digerir
Cantidad de dientes Respirar
Cuadrúpedo/bípedo Parpadear
Edad Dormir
Ahora veamos un ejemplo más cercano
a la informática: Una ventana. Clase
Ventana:
Datos Métodos
Etiqueta de encabezado
Cerrarse
Abrirse
Tipo de letra encabezado Minimizarse
Maximizarse
Color de Fondo
Color de letra encabezado
Como puede verse, en esencia la POO
lo que nos permite es ampliar el
tipo de
datos con los que se puede trabajar.
Todos los hombres comparten las
características de la clase hombre.
Sin
embargo todos los hombres son
distintos entre sí, en estatura,
pigmentación, etc.
A cada uno de los hombres
particulares se le llama “objetos de
la clase
hombre”. Cada niño que nace es una
instanciación de la clase hombre.
Entonces, los métodos los podemos
considerar sinónimos de
comportamientos,
operaciones, procedimientos.
La aplicación de los métodos dará
distintos resultados dependiendo de
los
valores con los que trabaje.
Para poder mandar mensajes a los
objetos, necesitamos un operador, a
este le
llamamos el operador de envío. Cada
lenguaje puede tener el suyo, pero
es
frecuente que se utilicen los dos
puntos (‘:’) o el punto (‘.’) (En
C++ es el punto
simple, igual que para referirnos a
los elementos de los struct’s).
Así, si queremos enviarle el mensaje
Caminar al objeto Juan de la clase
hombre,
escribiríamos lo siguiente:
El operador de envío hace que se
ejecute la porción del código
agrupada bajo el
nombre del método, y el método
trabajara con los datos propios de
la instancia de
la clase a la que se refiera.
Referencias a sí mismo
Un caso especial ocurre cuando
estamos codificando un método de una
clase y
tenemos que referirnos a un dato o
un método del propio objeto; estamos
creando
la clase, o por así decirlo, dentro
del objeto mismo.
Entonces, para referirse al propio
objeto, en OOP se hace uso de el
mismo, si
mismo, self (en ingles). Self
(algunos lenguajes utilizan “self”,
pero lo mas común
es que utilicen “this”11: así lo
hacen C++ y Java, por ejemplo.) en
OOP se refiere al
propio objeto con el que se esta
trabajando. Por lo tanto, si estamos
escribiendo
un método de una clase y queremos
enviar un mensaje al propio objeto,
escribiríamos:
This.Ocultar ( );
En este punto, puede parecer que un
programa no es más que un montón de
objetos con métodos que toman otros
objetos como parámetros y envían
mensajes a esos otros objetos. Esto
es, sin duda, mucho de lo que está
curriendo,
pero en otros apartados se verá cómo
hacer el trabajo de bajo nivel
detallado,
tomando decisiones dentro de un
método.
4.5 Encapsulado y ocultación de la
información: Clases
El concepto de clase, es simplemente
una abstracción que hacemos de
nuestra
experiencia sensible. El ser humano
tiende a agrupar seres o cosas
–objetos- con
características similares en grupos
–clases-. Así, aun cuando existen
por ejemplo
multitud de vasos diferentes,
podemos reconocer un vaso en cuanto
lo vemos,
incluso aun cuando ese modelo
concreto de vaso no lo hayamos visto
nunca. El
concepto vaso es una abstracción de
nuestra experiencia sensible. Al
igual que
ciertos ejemplos que pusimos en el
apartado anterior.
Quizás el ejemplo mas claro para
exponer esto lo tengamos en las
taxonomías;
los biólogos han dividido a todo ser
(vivo o inerte) sobre la tierra en
clases.
11 ver el apartado 12.5
Ellos, llaman a cada una de estas
parcelas reino, tipo, clase,
especie, orden,
familia, género, etc.; sin embargo,
nosotros a todas las llamaremos del
mismo
modo: clase. Así, hablaremos de la
clase animal, clase vegetal y clase
mineral, o
de la clase félidos y de las clases
leo (león) y tigres (tigre).
Cada clase posee unas cualidades que
la diferencian de las otras. Así,
por
ejemplo, los vegetales se
diferencian de los minerales –entre
otras muchas cosas-
en que los primeros son seres vivos
y los minerales no. De los animales
se
diferencian en que las plantas son
capaces de sintetizar clorofila a
partir de la luz
solar y los animales no.
Como vemos, el ser humano tiende, de
un modo natural a clasificar los
objetos del
mundo que le rodean en clases; son
definiciones estructuralistas de la
naturaleza
al estilo de la escuela francesa de
Saussure12.
Encapsulación
Un método de una clase puede llamar
a otros métodos de su misma clase y
pude
cambiar los valores de los datos de
su misma clase. Es esta la forma
correcta de
hacerse: los datos de una clase solo
deben ser alterados por los métodos
de su
clase; y no de forma directa (que es
como cambiamos los valores de las
variables
en un programa). Esta es una regla
de oro que no debe de olvidarse:
todos los
datos de una clase son privados y se
accede a ellos mediante métodos
públicos.
12 Ferdinand de Saussure. Lingüista
suizo, considerado el fundador de la
lingüística moderna.
Según los dos modos comentados,
tomemos como ejemplo un objeto
perteneciente a la clase marco,
modificaremos su dato nY1
(coordenada superior
izquierda) de dos modos distintos:
directamente y mediante el método
PonerY1 ( ).
Cambio directo: oCajaGeneral.nY1 =
12;
Cambio mediante invocación de
método: oCajaGeneral.PonerY1 (12);
Es más cómodo el primer método, ya
que hay que escribir menos para
cambiar el
valor del dato y además, a la hora
de construir la clase, no es
necesario crear un
método para cambiar cada uno de los
datos del objeto. Sin embargo, y
como se
ha ido comentando, la OOP recomienda
efusivamente que se utilice el
segundo
procedimiento. La razón es bien
simple: una clase debe ser una
estructura
cerrada, no se debe poder acceder a
ella si no es a través de los
métodos
definidos para ella. Si hacemos nY1
público (para que pueda ser accedido
directamente), estamos violando el
principio de encapsulación.
Encapsulación es la característica
de la POO que hace que un objeto sea
una
caja negra. Se le envía un mensaje
al objeto y este responde ejecutando
el
método apropiado.
Un método de una clase puede llamar
a métodos de la misma clase.
Gracias a la encapsulación una clase
que ha sido programada y probada
puede
usarse sin temor a que la
programación de otros objetos
basados en dichas clases
tengan errores.
En lugar de considerar el programa
como una enorme entidad, la
encapsulación
permite dividir un programa en
componentes más pequeños e
independientes.
Cada componente es autónomo y
realiza su labor independientemente
de los
demás componentes.
La encapsulación mantiene esa
independencia ocultando los detalles
internos de
cada componente, mediante una
interfaz externa.
Una interfaz lista los servicios
proporcionados por un componente. La
interfaz
actúa como un contrato con el mundo
exterior que define exactamente lo
que una
entidad externa puede hacer con el
objeto.
Una interfaz es un panel de control
para el objeto. Al definir una
interfaz puede
especificarse cuales métodos serán
definidos como públicos, privados y
protegidos.
Los métodos públicos son aquellos
que están disponibles para todo
aquel que
cree objetos basados en la clase.
Los métodos privados son aquellos
que solo son invocados por otros
métodos de
la clase.
Cuando un comportamiento se desee
poner a disposición del mundo
exterior,
debe tener acceso público. Lo que se
desee ocultar debe tener acceso
protegido o privado.
¿Porqué utilizar encapsulación?
. Independencia: Se puede reutilizar
el objeto en cualquier parte. Cuando
se
encapsulan de forma apropiada los
objetos, estos no están limitados a
un
programa en particular. Para
utilizarlo solo hay que poner en
acción su
interfaz.
. Transparencia: La encapsulación le
permite hacer cambios transparentes
al objeto, en tanto no se altere la
interfaz.
. Autonomía: El uso de un objeto
encapsulado no causará efectos
secundarios inesperados entre el
objeto y el resto del programa.
Puesto
que el objeto es autónomo, no tendrá
ninguna interacción con el programa
más allá de lo establecido por la
interfaz.
Gracias a la encapsulación, una
clase, cuando ha sido programada y
probada
hasta comprobar que no tiene fallos,
podemos usarla sin miedo a que al
programar otros objetos estos puedan
interferir con los primeros
produciendo
efectos colaterales indeseables que
arruinen nuestro trabajo; esto
también permite
depurar (eliminar errores de
programación) con suma facilidad, ya
que si un objeto
falla, el error solo puede estar en
esa clase y no en ninguna otra.
4.6 Modularidad
Un modulo puede definirse
diversamente, pero generalmente debe
ser un
componente de un sistema mas grande,
y opera independientemente dentro de
las funciones de ese sistema con los
otros componentes.
La modularidad es la propiedad que
mide hasta que punto han estado
compuestos de partes separadas
llamadas módulos. Los programas
tienen
muchas relaciones mutuas directas
entre cualquiera de dos partes
aleatorias del
código del programa.
4.7 Polimorfismo
Se denomina polimorfismo a la
capacidad del código de un programa
para ser
utilizado con diferentes tipos de
datos u objetos. También se puede
aplicar a la
propiedad que poseen algunas
operaciones de tener un
comportamiento diferente
dependiendo del objeto (o tipo de
dato) sobre el que se aplican.
El concepto de polimorfismo se puede
aplicar tanto a funciones como a
tipos de
datos. Así nacen los conceptos de
funciones polimórficas y tipos
polimórficos. Las
primeras son aquellas funciones que
pueden evaluarse y/o ser aplicadas a
diferentes tipos de datos de forma
indistinta; los tipos polimórficos,
por su parte,
son aquellos tipos de datos que
contienen al menos un elemento cuyo
tipo no está
especificado.
Se puede clasificar el polimorfismo
en dos grandes clases:
• Polimorfismo dinámico (o
polimorfismo ad hoc) es aquél en el
que el
código no incluye ningún tipo de
especificación sobre el tipo de
datos sobre
el que se trabaja. Así, puede ser
utilizado a todo tipo de datos
compatible.
• Polimorfismo estático (o
polimorfismo paramétrico) es aquél
en el que
los tipos a los que se aplica el
polimorfismo deben ser explicitados
y
declarados uno por uno antes de
poder ser utilizados.
El polimorfismo dinámico unido a la
herencia es lo que en ocasiones se
conoce
como programación genérica.
Pongamos por ejemplo las clase
hombre, vaca y perro, si todos les
damos la
orden –enviamos el mensaje-Come,
cada uno de ellos sabe como hacerlo
y
realizara este comportamiento a su
modo.
Veamos otro ejemplo algo más
ilustrativo. Tomemos las clases
barco, avión y
coche, todas ellas derivadas de la
clase padre vehículo; si les
enviamos el
mensaje Desplázate, cada una de
ellas sabe como hacerlo.
Realmente, y para ser exactos, los
mensajes no se envían a las clases,
sino a
todos o algunos de los objetos
instaciados de las clases. Así, por
ejemplo,
podemos decirle a los objetos Juan
Sebastián el Cano y Kontiqui, de la
clase
barco que se desplacen, con los que
el resto de los objetos de esa clase
permanecerán inmóviles.
Del mismo modo, si tenemos en
pantalla cinco recuadros (marcos) y
tres textos,
podemos decirle a tres de los
recuadros y a dos de los textos que
cambien de
color y no decírselo a los demás
objetos. Todos estos sabrán como
hacerlo
porque hemos redefinido para cada
uno de ellos su método Pintarse que
bien
podría estar en la clase padre
Visual (conjunto de objetos que
pueden visualizarse
en pantalla).
En programación tradicional, debemos
crear un nombre distinto para la
acción de
pintarse, si se trata de un texto o
de un marco; en POO el mismo nombre
nos sirve
para todas las clases creadas si así
lo queremos, lo que suele ser
habitual. El
mismo nombre suele usarse para
realizar acciones similares en
clases diferentes.
Si enviamos el mensaje Imprímete a
objetos de distintas clases, cada
uno se
imprimirá como le corresponda, ya
que todos saben como hacerlo.
El polimorfismo facilita el trabajo,
ya que gracias a él, el número de
nombre de
métodos que tenemos que recordar
disminuye ostensiblemente.
La mayor ventaja la obtendremos en
métodos con igual nombre aplicados a
las
clases que se encuentran próximas a
la raíz del árbol de clases, ya que
estos
métodos afectaran a todas las clases
que de ellas se deriven.
4.8 Jerarquización: Herencia y
Objetos compuestos
Herencia
Esta es la cualidad más importante
de un sistema POO, la que nos dará
mayor
potencia y productividad,
permitiéndonos ahorrar horas y horas
de codificación y
de depuración de errores.
Sería mejor si pudiéramos hacer uso
de una clase ya existente, clonarla,
y
después hacer al "clon" las
adiciones y modificaciones que sean
necesarias.
Efectivamente, esto se logra
mediante la herencia, con la
excepción de que si se
cambia la clase original (denominada
la clase base, clase súper o clase
padre), el
"clon" modificado (denominado clase
derivada, clase heredada, subclase o
clase
hijo) también reflejaría esos
cambios.
Puede haber más de una clase
derivada. Un tipo hace más que
definir los límites
de un conjunto de objetos; también
tiene relaciones con otros tipos.
Dos tipos
pueden tener características y
comportamientos en común, pero un
tipo puede
contener más características que
otro y también puede manipular más
mensajes
(o gestionarlos de manera distinta).
La herencia expresa esta semejanza
entre
tipos haciendo uso del concepto de
tipos base y tipos derivados. Un
tipo base
contiene todas las características y
comportamientos que comparten los
tipos que
de él se derivan. A partir del tipo
base, es posible derivar otros tipos
para expresar
las distintas maneras de llevar a
cabo esta idea.
Por ejemplo, una máquina de
reciclaje de basura clasifica los
desperdicios. El tipo
base es "basura", y cada desperdicio
tiene su propio peso, valor, etc. y
puede ser
fragmentado, derretido o
descompuesto.
Así, se derivan tipos de basura más
específicos que pueden tener
características
adicionales (una botella tiene un
color), o comportamientos (el
aluminio se puede
modelar, una lata de acero tiene
capacidades magnéticas). Además,
algunos
comportamientos pueden ser distintos
(el valor del papel depende de su
tipo y
condición). El uso de la herencia
permite construir una jerarquía de
tipos que
expresa el problema que se trata de
resolver en términos de los propios
tipos.
Un segundo ejemplo es el clásico de
la "figura geométrica" utilizada
generalmente
en sistemas de diseño por computador
o en simulaciones de juegos. El tipo
base
es "figura" y cada una de ellas
tiene un tamaño, color, posición,
etc. Cada figura
puede dibujarse, borrarse, moverse,
colorearse, etc.
A partir de ésta, se pueden derivar
(heredar) figuras específicas:
círculos,
cuadrados, triángulos, etc.,
pudiendo tener cada uno de los
cuales características
y comportamientos adicionales.
Algunos comportamientos pueden ser
distintos,
como pudiera ser el cálculo del área
de los distintos tipos de figuras.
La jerarquía
de tipos engloba tanto las
similitudes como las diferencias
entre las figuras.
Otro ejemplo, la clase león que se
comenta en la figura de la
clasificación
taxonómica en el apartado 4.5,
hereda cualidades –métodos- de todas
las clases
predecesoras –padres- y posee
métodos propios, diferentes a los
del resto de las
clases. Es decir, las clases van
especializándose según se avanza en
el árbol
taxonómico. Cada vez que creamos una
clase heredada de otra (la padre)
añadimos métodos a la clase padre o
modificamos alguno de los métodos de
la
clase padre.
Veamos que hereda la clase león de
sus clases padre:
Clase Que hereda
Vertebrados Espina dorsal
Mamíferos Se alimenta con leche
materna
Carnívoros Al ser adultos se
alimentan de carne
La clase león hereda todos los
métodos de las clases padre y añade
métodos
nuevos que forman su clase
distinguiéndola del resto de las
clases: por ejemplo el
color de su piel.
Pongamos ahora un ejemplo algo más
informático: supongamos que usted ha
construido una clase que le permite
leer números enteros desde teclado
con un
formato determinado, calcular su IVA
y almacenarlos en un archivo. Si
desea
poder hacer lo mismo con números
reales (para que admitan decimales),
solo
deberá crear una nueva subclase para
que herede de la clase padre todos
sus
métodos y redefinirá solo el método
de lectura de teclado. Esta nueva
clase sabe
almacenar y mostrar los números con
formato porque lo sabe su clase
padre.
Las cualidades comunes que comparten
distintas clases, pueden y deben
agruparse para formar una clase
padre. Por ejemplo, usted podría
derivar las
clases presupuesto y factura de la
superclase pedidos, ya que estas
clases
comparten características comunes.
De este modo, la clase padre
poseería los
métodos comunes a todas ellas y solo
tendríamos que añadir aquellos
métodos
propios de cada una de las
subclases, pudiendo reutilizar el
código escrito en la
superclase desde cada una de las
clases derivadas. Así, si enseñamos
a la clase
padre a imprimirse, cada uno de los
objetos de las clases inferiores
sabrán
automáticamente y sin escribir ni
una sola línea más de código
imprimirse.
Es así, que la herencia es la
cualidad mas importante de la POO ya
que le permite
reutilizar todo el código escrito
para las superclases re-escribiendo
solo aquellas
diferencias que existan entre estas
y las subclases.
Muchas veces las clases
–especialmente aquellas que se
encuentran próximas a
la raíz en el árbol de la jerarquía
de clases- son abstractas. Es decir,
solo existen
para proporcionar una base para la
creación de clases mas especificas,
y por lo
tanto no puede instanciarse de
ellas; son las clases virtuales.
Una subclase hereda de su superclase
solo aquellos miembros visibles
desde la
clase hija y por lo tanto solo puede
redefinir estos.
Una subclase tiene forzosamente que
redefinir aquellos métodos que han
sido
definidos como abstractos en la
clase padre o padres.
Es habitual que la herencia suscite
un pequeño debate: ¿debería la
herencia
superponer sólo las funciones de la
clase base (sin añadir nuevas
funciones
miembro que no se encuentren en
ésta)?. Esto significaría que el
tipo derivado sea
exactamente el mismo tipo que el de
la clase base, puesto que tendría
exactamente la misma interfaz.
Consecuentemente, es posible
sustituir un objeto
de la clase derivada por otro de la
clase base. A esto se le puede
considerar
sustitución pura, y a menudo se le
llama el principio de sustitución.
De cierta
forma, ésta es la manera ideal de
tratar la herencia. Habitualmente, a
la relación
entre la clase base y sus derivadas
que sigue esta filosofía se le
denomina
relación es-un, pues es posible
decir que "un círculo es un
polígono". Una manera
de probar la herencia es determinar
si es posible aplicar la relación
es-un a las
clases en liza, y tiene sentido.
Hay veces en las que es necesario
añadir nuevos elementos a la
interfaz del tipo
derivado, extendiendo así la
interfaz y creando un nuevo tipo.
Éste puede ser
también sustituido por el tipo base,
pero la sustitución no es perfecta
pues las
nuevas funciones no serían
accesibles desde el tipo base. Esta
relación puede
describirse como la relación
es-como-un" el nuevo tipo tiene la
interfaz del viejo
pero además contiene otras
funciones, así que no se puede decir
que sean
exactamente iguales. Considérese por
ejemplo un acondicionador de aire.
Supongamos que una casa está
cableada y tiene las botoneras para
refrescarla,
es decir, tiene una interfaz que
permite controlar la temperatura.
Imagínese que se
estropea el acondicionador de aire y
se reemplaza por una bomba de calor
que
puede tanto enfriar como calentar.
La bomba de calor es-como-un
acondicionador
de aire, pero puede hacer más
funciones. Dado que el sistema de
control de la
casa está diseñado exclusivamente
para controlar el enfriado, se
encuentra
restringido a la comunicación con la
parte "enfriadora" del nuevo objeto.
Es
necesario extender la interfaz del
nuevo objeto, y el sistema existente
únicamente
conoce la interfaz original.
Por supuesto, una vez que uno ve
este diseño, está claro que la clase
base
"sistema de enfriado" no es lo
suficientemente general, y debería
renombrarse a
"sistema de control de temperatura"
de manera que también pueda incluir
calentamiento -punto en el que el
principio de sustitución funcionará.
Sin embargo,
este diagrama es un ejemplo de lo
que puede ocurrir en el diseño y en
el mundo
real.
Cuando se ve el principio de
sustitución es fácil sentir que este
principio (la
sustitución pura) es la única manera
de hacer las cosas, y de hecho, es
bueno
para los diseños que funcionen así.
Pero hay veces que está claro que
hay que
añadir nuevas funciones a la
interfaz de la clase derivada.
4.9 Ligadura Dinámica
La ligadura en las llamadas a
métodos
La conexión de una llamada a un
método se denomina ligadura. Cuando
se lleva a
cabo la ligadura antes de ejecutar
el programa (por parte del
compilador y el
montador, cuando lo hay) se denomina
ligadura temprana. Puede que este
término parezca extraño pues nunca
ha sido una opción con los lenguajes
procedurales. Los compiladores de C
tienen un único modo de invocar a un
método utilizando la ligadura
temprana.
La solución es la ligadura tardía,
que implica que la correspondencia
se da en
tiempo de ejecución, basándose en el
tipo de objeto. La ligadura tardía
se
denomina también dinámica o en
tiempo de ejecución.
Cuando un lenguaje implementa la
ligadura tardía, debe haber algún
mecanismo
para determinar el tipo de objeto en
tiempo de ejecución e invocar al
método
adecuado. Es decir, el compilador
sigue sin saber el tipo de objeto,
pero el
mecanismo de llamada a métodos
averigua e invoca al cuerpo de
método
correcto. El mecanismo de la
ligadura tardía varía de un lenguaje
a otro, pero se
puede imaginar que es necesario
instalar algún tipo de información
en los objetos.
Toda ligadura de métodos en Java se
basa en la ligadura tardía a menos
que se
haya declarado un método como
constante. Esto significa que
ordinariamente no
es necesario tomar decisiones sobre
si se dará la ligadura tardía, sino
que esta
decisión se tomará automáticamente.
5. Diseño tradicional vrs. Diseño OO
Como hemos visto hasta ahora, el
Diseño Orientado a Objetos ofrece
muchas
alternativas para la resolución de
problemas al programador, y hemos
mencionado
también los distintos paradigmas de
programación.
Ahora, repasemos puntos clave del
diseño OO:
• El diseño OO se enfoca sobre
objetos y clases basados en el mundo
real.
• Hace un énfasis en el estado,
comportamientos e interacciones de
objetos
• Provee las siguientes ventajas:
o Desarrollo rápido de aplicaciones
(RAD)
o Aumenta la calidad
o Provee un fácil mantenimiento
o Mejora la modificación
o Incrementa el reutilizamiento de
software
Pero como todo en este mundo,
también tiene sus limitaciones e
inconvenientes.
De las primeras no cabe ni hablar,
porque aun cuando sea el sistema mas
apropiado del que se dispone para
programar, todavía se enfrenta con
ciertos
problemas de diseño.
El mayor inconveniente real proviene
de un “error” de planteamiento; y
como casi
siempre, estos son de mucha mayor
dificultad a la hora de
solucionarlos. El
problema, según comenta uno de los
mejores analistas de hoy en día,
Jeff
Duntemann15, en un articulo de la
revista Dr. Dobbs16, es que “la
encapsulación y
la herencia se hallan en esquinas
opuestas de la casa”.
15 Escritor, Editor, Tecnólogo. Más
en www.duntemann.com
16 Dr. Dobbs Journal, más en
www.ddj.com
Es decir, la encapsulación choca
frontalmente con la herencia, y sin
embargo, son
dos piedras angulares de la POO.
Por un lado decimos que los objetos
deben ser totalmente independientes
y
autónomos, y por otro, al heredar
unas clases de otras, estamos
dejando fuera de
un objeto perteneciente a una clase
hija gran parte de la información
que esta
necesita para poder comportarse.
Otro inconveniente que se puede
observar es el que estriba en la
imposibilidad de
utilización conjunta de objetos de
distintos programadores.
Un ejemplo simple, supongamos que se
monta un coche en un garaje, puede
comprar un carburador de cualquier
marca y montarlo en un coche de otra
marca,
unos asientos de uno y montarlos en
la carrocería de otro; esto mismo
puede
hacerse en POO.
Si Microsoft fabrica la clase Menú,
que deriva de la clase Visual y
Borland fabrica
la clase Ventana aunque también
derive de la clase Visual, no puede
conseguir
coger el menú de una y la ventana de
la otra, a menos que todas las
clases
superiores (en este caso solo una)
sean exactamente iguales: tengan el
mismo
nombre, contengan los mismos datos y
los mismos métodos y en estos, todos
los
parámetros deben coincidir en orden
y en tipo.
Este problema por ahora no tiene
solución, y lo peor es que no se
vislumbra que la
tenga en un futuro próximo, ya que
para ello seria necesario normalizar
las clases
(al menos las mas habituales), pero
si no nos ponemos de acuerdo para
utilizar un
mismo HTML ¿Cómo nos vamos a poner
de acuerdo para esto?
Critica
Los taxonomías jerárquicas no
coinciden a menudo con el mundo real
y los
cambios del mundo real según algunos
críticos, y debe evitarse. Sin
embargo,
muchos defensores de POO también
hacen pensar en evitar las
jerarquías y usar
las técnicas de POO en cambio como
la composición.
También, muchos sienten que POO
corre lo opuesto a la filosofía de
planeación
correlativa y base de datos
relacionales, mientras se vuelve a
los arreglos de la
base de datos de navegación de los
años sesenta. No está claro que ésta
es la
falta de POO, desde que la
planeación de bases de datos es
fundamentalmente
basada en las diferentes premisas
que la planeación basada en objetos.
En
cualquier caso, las bases de datos
relacionales trazan a las
asociaciones en los
modelos basados en objetos, y las
diferencias parecen ser
completamente
debidas a las diferencias en el
enfoque.
Hay una historia de
desinterpretación de la relación
entre planear basado en
objetos y en la correlación a lo que
puede enturbiar este problema. Hay
también,
variaciones en las opiniones sobre
los papeles y definiciones de cada
uno.
La desigualdad de impedancia entre
las bases de datos y POO se causa
por la
diferencia de balanza entre
funcionamientos realizados por los
objetos y bases de
datos; las transacciones de la base
de datos, la unidad más pequeña de
trabajo
realizada por las bases de datos,
son mucho más grandes que cualquier
funcionamiento proporcionado por los
objetos de POO.
Mientras se exige que POO es buena
para "aplicaciones grandes”, otros
sienten
que deben reducirse las aplicaciones
grandes en cambio a muchas
aplicaciones
pequeñas, como procedimientos
manejados a eventos que " se
alimentan" fuera
de una base de datos y armazones de
interfaz de usuario basadas en
declaratorias de programación.
Está reconocido que POO
necesariamente no quiere decir falta
de complejidad.
6. Evolución de los Lenguajes
Orientados a Objetos
Los conceptos de la programación
orientada a objetos tienen origen en
Simula 67,
un lenguaje diseñado para hacer
simulaciones, creado por Ole-Johan
Dahl y
Kristen Nygaard del Centro de
Cómputo Noruego en Oslo. Según se
informa, la
historia es que trabajaban en
simulaciones de naves, y fueron
confundidos por la
explosión combinatoria de cómo las
diversas cualidades de diversas
naves podían
afectar unas a las otras. La idea
ocurrió para agrupar los diversos
tipos de naves
en diversas clases de objetos,
siendo responsable cada clase de
objetos de definir
sus propios datos y comportamientos.
Fueron refinados más tarde en
Smalltalk,
que fue desarrollado en Simula en
Xerox PARC(Palo Alto Research
Center) pero
diseñado para ser un sistema
completamente dinámico en el cual
los objetos se
podrían crear y modificar "en
marcha" en lugar de tener un sistema
basado en
programas estáticos.
La programación orientada a objetos
tomó posición como la metodología de
programación dominante a mediados de
los años ochenta, en gran parte
debido a
la influencia de C++, una extensión
del lenguaje de programación C. Su
dominación fue consolidada gracias
al auge de las Interfaces gráficas
de usuario
(GUI por sus siglas en ingles), para
los cuales la programación orientada
a objetos
está particularmente bien adaptada.
En el ETH de Zürich, Niklaus Wirth y
sus colegas tuvieron también
investigaciones
como tópicos de abstracción de datos
y programación modular. El lenguaje
Modula-2 incluye ambos, y su diseño
sucesor, Oberon incluye una
aproximación
distintiva a orientación a objetos,
clases y semejantes. El acercamiento
es
diferente a Smalltalk, y muy
diferente a C++.
Las características de Orientación a
Objetos han sido añadidas a muchos
lenguajes existentes durante el
tiempo, incluyendo Ada, BASIC, Lisp,
Fortran,
Pascal, y otros. Agregando esos
aspectos a lenguajes que no fueron
inicialmente
diseñados para ello condujo a
problemas con la compatibilidad y
mantenimiento
de código. Los lenguajes Orientados
a Objetos “Puros”, por otra parte,
carecían de
aspectos que muchos programadores
han venido dependiendo. Para cruzar
esta
brecha, muchos intentos han sido
hechos para crear nuevos lenguajes
basados en
métodos Orientados a Objetos pero
permitiendo algunos aspectos
procedurales
en formas “seguras”.
El lenguaje Eiffel de Bertrand
Meyer’s17 fue un temprano y
moderadamente exitoso
lenguaje con esos objetivos.
En la década pasada Java ha emergido
ampliamente en uso parcialmente por
su
similitud a C y C++, pero quizás lo
más importante de su implementación
es el uso
de una maquina virtual que es
proyectada a correr código
inalterado sobre muchas
plataformas distintas. Esta ultima
característica lo ha hecho muy
atractivo en
amplias tiendas de desarrollo y
ambientes heterogéneos.
La iniciativa de la plataforma .NET
de Microsoft ha tenido un objetivo
similar e
incluye/soporta varios nuevos
lenguajes, o variantes de algunos
viejos.
Más recientemente, un número de
lenguajes ha surgido para ser
primariamente
orientados a objetos aun compatibles
con la metodología procedural, tales
como
Python y Ruby. Al lado de Java,
probablemente el mas comercial
lenguaje
orientado a objetos reciente es
Visual Basic .NET y C# diseñados
para la
plataforma .NET de Microsoft.
Tal como la programación procedural
lleva a refinamientos de técnicas
como la
programación estructurada, el
software orientado a objetos moderno
diseña
métodos que incluye refinamiento
como el uso de diseño de patrones,
diseño por
convenios, y lenguajes de modelado
(tal es UML, usado en ingeniería de
software).
17 Bertrand Meyer, (nacido en
Francia en 1950). Es uno de los
primeros y vocales más proponentes
de la POO. Sus libros
sobre “Construcción de Software” son
considerados los mejores trabajos
presentes para la presentación de
POO.
Para el aprendizaje
En el pasado, han existido muchas
disputas como cual es el mejor
lenguaje para
comenzar con la programación
orientada a objetos. Hay dos
diferentes enfoques a
tomar cuando se comienza con este
estilo de programación. El primero
es la idea
que lo mejor es empezar con un
lenguaje simple como Java, donde el
aprendizaje
se enfoca sobre la orientación a
objetos y no es perturbado por
semánticas
complejas del lenguaje. Aun así,
otra razón es que lo mejor es
empezar con un
lenguaje más complicado como C++, el
cual soporta con más precisión todas
las
estructuras y capacidades prescritas
por el lenguaje de modelado
unificado (UML),
aunque no hay un lenguaje conocido
el cual esencialmente soporte
totalmente las
capacidades de UML. En la versión
utilizada para el entorno de
desarrollo Eclipse
para este ensayo esta instalado la
versión Eclipse UML 3.10 Free
Edition de
Omondo.
7. Lenguajes orientados a objetos
Entre los lenguajes orientados a
objetos destacan los siguientes:
• Smalltalk
• Objective-C
• C++
• Ada 95
• Java
• Ocaml
• Python
• Delphi
• Lexico (en castellano)
• C#
• Eiffel
• Ruby
• ActionScript
• Visual Basic
• PHP
• PowerBuilder
• Clarion
Estos lenguajes de programación son
muy avanzados en orientación a
objetos.
Al igual que C++ otros lenguajes,
como OOCOBOL, OOLISP, OOPROLOG y
Object REXX, han sido creados
añadiendo extensiones orientadas a
objetos a un
lenguaje de programación clásico.
Un nuevo paso en la abstracción de
paradigmas de programación es la
Programación Orientada a Aspectos
(POA). Aunque es todavía una
metodología
en estado de maduración, cada vez
atrae a más investigadores e incluso
proyectos comerciales en todo el
mundo.
8. Java
8.1 ¿Qué es Java?
Java es un lenguaje de desarrollo de
propósito general, y como tal es
válido para
realizar todo tipo de aplicaciones
profesionales.
Entonces, ¿es simplemente otro
lenguaje más? Definitivamente no.
Incluye una
combinación de características que
lo hacen único y está siendo
adoptado por
multitud de fabricantes como
herramienta básica para el
desarrollo de aplicaciones
comerciales de gran repercusión.
¿Qué lo hace distinto de los demás
lenguajes?
Una de las características más
importantes es que los programas
“ejecutables”,
creados por el compilador de Java,
son independientes de la
arquitectura. Se
ejecutan indistintamente en una gran
variedad de equipos con diferentes
microprocesadores y sistemas
operativos.
• De momento, es público. Puede
conseguirse un JDK (Java Developer's
Kit) o
Kit de desarrollo de aplicaciones
Java gratis. No se sabe si en un
futuro seguirá
siéndolo.
• Permite escribir Applets (pequeños
programas que se insertan en una
página
HTML) y se ejecutan en el ordenador
local.
• Se pueden escribir aplicaciones
para intrarredes, aplicaciones
cliente/servidor,
aplicaciones distribuidas en redes
locales y en Internet.
• Es fácil de aprender y está bien
estructurado.
• Las aplicaciones son fiables.
Puede controlarse su seguridad
frente al acceso a
recursos del sistema y es capaz de
gestionar permisos y criptografía.
También,
según Sun, la seguridad frente a
virus a través de redes locales e
Internet está
garantizada. Aunque al igual que ha
ocurrido con otras tecnologías y
aplicaciones, se han descubierto, y
posteriormente subsanado, “agujeros”
en la
seguridad de Java.
¿Qué se puede programar con Java?
Si tenía preconcebida la idea de que
con Java sólo se programan applets
para
páginas Web, está completamente
equivocado. Ya que Java es un
lenguaje de
propósito general, puede programarse
en él cualquier cosa:
• Aplicaciones independientes. Como
con cualquier otro lenguaje de
propósito
general.
• Applets. Pequeñas aplicaciones que
se ejecutan en un documento HTML,
siempre y cuando el navegador
soporte Java, como ocurre con los
navegadores HotJava y las últimas
versiones de Netscape y el
explorador de
Internet de Microsoft.
Para todo aquel que no conozca la
programación orientada a objetos,
este
lenguaje es ideal para aprender
todos sus conceptos, ya que en cada
paso de su
aprendizaje se va comprobando que
las cosas se hacen en la forma
natural de
hacerlas, sin sorpresas ni
comportamientos extraños de los
programas. A medida
que se va aprendiendo, se va
fomentando en el programador, y sin
esfuerzo, un
buen estilo de programación
orientada a objetos. En realidad, no
puede ser de otra
forma, ya que Java impide “hacer
cosas extrañas” y, además, no
permite
“abandonar” la programación
orientada a objetos, como ocurre con
otros lenguajes
de programación. Esto es bastante
conveniente, de lo contrario, un
programador
que está aprendiendo puede sentir la
tentación de “volver” a lo que
conoce (la
programación tradicional).
8.2 Breve Historia de Java
El lenguaje Java™ fue creado por Sun
Microsystems Inc. en un proceso por
etapas que arranca en 1990, año en
el que Sun creó un grupo de trabajo,
liderado
por James Gosling, para desarrollar
un sistema para controlar
electrodomésticos e
incluso PDAs o Asistentes Personales
(pequeños ordenadores) que, además,
permitiera la conexión a redes de
ordenadores. Se pretendía crear un
hardware
polivalente, con un Sistema
Operativo eficiente (SunOS) y un
lenguaje de
desarrollo denominado Oak (roble),
el precursor de Java. El proyecto
finalizó en
1992 y resultó un completo fracaso
debido al excesivo coste del
producto, con
relación a alternativas similares,
tras lo cual el grupo se disolvió.
Por entonces aparece Mosaic y la
World Wide Web. Después de la
disolución del
grupo de trabajo, únicamente quedaba
del proyecto el lenguaje Oak.
Gracias a
una acertada decisión de distribuir
libremente el lenguaje por la Red de
Redes y al
auge y la facilidad de acceso a
Internet, propiciado por la WWW, el
lenguaje se
popularizó y se consiguió que una
gran cantidad de programadores lo
depurasen y
terminasen de perfilar la forma y
usos del mismo. A partir de este
momento, el
lenguaje se difunde a una velocidad
vertiginosa, añadiéndosele numerosas
clases
y funcionalidad para TCP/IP. El
nombre del lenguaje tuvo que ser
cambiado ya
que existía otro llamado Oak. El
nombre “Java” surgió en una de las
sesiones de
“brainstorming” celebradas por el
equipo de desarrollo del lenguaje.
Buscaban un
nombre que evocara la esencia de la
tecnología (viveza, animación,
rapidez,
interactividad…). Java fue elegido
de entre muchísimas propuestas. No
es un
acrónimo, sino únicamente algo
humeante, caliente y que a muchos
programadores les gusta beber en
grandes cantidades: una taza de café
(Java en
argot Inglés americano). De esta
forma, Sun lanzó las primeras
versiones de Java
a principios de 1995.
Desde entonces, Sun ha sabido
manejar inteligentemente el éxito
obtenido por su
lenguaje, concediéndose licencias a
cualquiera sin ningún problema,
fomentando
su uso entre la comunidad
informática y extendiendo las
especificaciones y
funcionalidad del lenguaje.
8.3 Características de Java
• Es intrínsecamente orientado a
objetos.
• Funciona perfectamente en red.
• Aprovecha características de la
mayoría de los lenguajes modernos
evitando
sus inconvenientes. En particular
los del C++.
• Tiene una gran funcionalidad
gracias a sus librerías (clases).
• NO tiene punteros manejables por
el programador, aunque los maneja
interna
y transparentemente.
• El manejo de la memoria no es un
problema, la gestiona el propio
lenguaje y
no el programador.
• Genera aplicaciones con pocos
errores posibles.
• Incorpora Multi-Threading (para
permitir la ejecución de tareas
concurrentes
dentro de un mismo programa).
El lenguaje Java puede considerarse
como una evolución del C++. La
sintaxis es
parecida a la de este lenguaje, por
lo que se hace referencia a dicho
lenguaje. A
pesar de que puede considerarse como
una evolución del C++ no acarrea los
inconvenientes del mismo, ya que
Java fue diseñado “partiendo de
cero”, es decir,
un lenguaje “puro” y no necesitaba
ser compatible con versiones
anteriores de
ningún lenguaje como ocurre con C++
y C.
Gracias a que fue diseñado
“partiendo de cero” ha conseguido
convertirse en un
lenguaje orientado a objetos puro,
limpio y práctico. No permite
programar
mediante otra técnica que no sea la
programación orientada a objetos y,
una vez
superado el aprendizaje de la
programación orientada a objetos, es
realmente
sencillo aprender Java.
¿El lenguaje es Compilado o
Interpretado? Ni una cosa ni la
otra. Aunque
estrictamente hablando es
interpretado, necesita de un proceso
previo de
compilación. Una vez “compilado” el
programa, se crea un archivo que
almacena
lo que se denomina bytecodes o
j_code (seudo código prácticamente
al nivel de
código máquina). Para ejecutarlo, es
necesario un “intérprete”, la JVM
(Java
Virtual Machine) máquina virtual
Java. De esta forma, es posible
compilar el
programa en una estación UNIX y
ejecutarlo en otra con Windows
utilizando la
máquina virtual Java para Windows.
Esta JVM se encarga de leer los
bytecodes y
traducirlos a instrucciones
ejecutables directamente en un
determinado
microprocesador, de una forma
bastante eficiente.
Que el programa deba ser
“interpretado” no hace que sea poco
eficiente en cuanto
a velocidad, ya que la
interpretación se hace prácticamente
al nivel de código
máquina. Por ejemplo, es mucho más
rápido que cualquier otro programa
interpretado como por ejemplo Visual
Basic, aunque es más lento que el
mismo
programa escrito en C++. Esta
deficiencia en cuanto a la
velocidad, puede ser
aminorada por los compiladores
Just-In-Time (JIT). Un compilador
JIT transforma
los bytecodes de un programa o un
applet en código nativo de la
plataforma donde
se ejecuta, por lo que es más
rápido. Suelen ser incorporados por
los
navegadores, como Netscape o
Internet Explorer.
El lenguaje Java es robusto. Las
aplicaciones creadas en este
lenguaje son
susceptibles de contener pocos
errores, principalmente porque la
gestión de
memoria y punteros es realizada por
el propio lenguaje y no por el
programador.
Bien es sabido que la mayoría de los
errores en las aplicaciones vienen
producidos por fallos en la gestión
de punteros o la asignación y
liberación de
memoria. Además, el lenguaje
contiene estructuras para la
detección de
excepciones (errores de ejecución
previstos) y permite obligar al
programador a
escribir código fiable mediante la
declaración de excepciones posibles
para una
determinada clase reutilizable.
La Máquina Virtual Java (JVM)
La máquina virtual Java es la idea
revolucionaria18 del lenguaje. Es la
entidad que
proporciona la independencia de
plataforma para los programas Java
“compilados”
en byte-code.
18 Otros sistemas en el pasado, como
por ejemplo el Pascal UCSD
compilaban a un código intermedio
(p-code) que luego
era interpretado al ejecutar el
programa.
Un mismo programa fuente compilado
en distintas plataformas o sistemas
operativos, genera el mismo archivo
en byte-code. Esto es lógico, ya que
se
supone que el compilador de Java
traduce el archivo fuente a código
ejecutable
por una máquina que únicamente
existe en forma virtual (aunque se
trabaja en la
construcción de microprocesadores
que ejecuten directamente el
byte-code).
Evidentemente, si un mismo programa
en byte-code puede ser ejecutado en
distintas plataformas es porque
existe un traductor de ese byte-code
a código
nativo de la máquina sobre la que se
ejecuta. Esta tarea es realizada por
la JVM.
Existe una versión distinta de esta
JVM para cada plataforma. Esta JVM
se carga
en memoria y va traduciendo “al
vuelo”, los byte-codes a código
máquina. La JVM
no ocupa mucho espacio en memoria,
piénsese que fue diseñada para poder
ejecutarse sobre pequeños
electrodomésticos como teléfonos,
televisores, etc.
8.4 Novedades en la versión 1.5
1. Introducción
En este documento se resumen las
principales novedades que ofrece la
versión
1.5 de Java, separándolas en
diferentes áreas. Para una
explicación más
detallada, consultar la página de
Sun:
http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html
2. Novedades en la máquina virtual
Autoajuste de memoria mejorado
La capacidad de autoajustar la
cantidad de memoria necesaria (pila,
recolector de
basura, etc.) se ve mejorada en esta
versión.
Compartir clases
Al instalar la máquina virtual, se
cargan en memoria un conjunto de
clases del
sistema, en forma de representación
interna, de forma que las siguientes
llamadas
a la máquina virtual ya encuentren
estas clases mapeadas en memoria, y
se
permita que los datos de estas
clases se compartan entre múltiples
procesos
dentro de la JVM.
Ajuste del recolector de basura
Relacionado con el autoajuste de
memoria, el recolector de basura
también se
autoadapta a las necesidades de
memoria de la aplicación, para
evitar que el
usuario tenga que ajustar su tamaño
y características desde línea de
comandos.
Tratamiento de errores fatales
El mecanismo de listado de errores
fatales se ha mejorado de forma que
se
obtengan mejores diagnósticos a
partir de las salidas generadas por
dichos
errores.
3. Novedades en el lenguaje
Tipos de datos parametrizados
(generics)
Esta mejora permite tener
colecciones de tipos concretos de
datos, lo que permite
asegurar que los datos que se van a
almacenar van a ser compatibles con
un
determinado tipo o tipos. Por
ejemplo, podemos crear un Vector que
sólo
almacene Strings, o una HashMap que
tome como claves Integers y como
valores
Vectors. Además, con esto nos
ahorramos las conversiones cast al
tipo que
deseemos, puesto que la colección ya
se asume que será de dicho tipo.
Ejemplo
// Vector de cadenas
Vector<String> v = new
Vector<String>();
v.addElement("Hola");
String s = v.getElementAt(0);
v.addElement(new Integer(20)); //
Daría error!!
// HashMap con claves enteras y
valores de vectores
HashMap<Integer, Vector> hm = new
HashMap<Integer, Vector>();
hm.put(1, v);
Vector v2 = hm.get(1);
Autoboxing
Esta nueva característica evita al
programador tener que establecer
correspondencias manuales entre los
tipos simples (int, double, etc.) y
sus
correspondientes wrappers o tipos
complejos (Integer, Double, etc.).
Podremos
utilizar un int donde se espere un
objeto complejo (Integer), y
viceversa.
Ejemplo
Vector<Integer> v = new
Vector<Integer>();
v.addElement(30);
Integer n = v.getElementAt(0);
n = n+1;
Mejoras en Ciclos
Se mejoran las posibilidades de
recorrer colecciones y arrays,
previniendo índices
fuera de rango, y pudiendo recorrer
colecciones sin necesidad de acceder
a sus
iteradores (Iterator).
Ejemplo
// Recorre e imprime todos los
elementos de un array
int[] arrayInt = {1, 20, 30, 2, 3,
5};
for(int elemento: arrayInt)
System.out.println (elemento);
// Recorre e imprime todos los
elementos de un Vector
Vector<String> v = new
Vector<String>();
for(String cadena: v)
System.out.println (cadena);
Tipo enum
El tipo enum que se introduce
permite definir un conjunto de
posibles valores o
estados, que luego podremos utilizar
donde queramos:
Ejemplo
// Define una lista de 3 valores y
luego comprueba en un switch// cuál
es el valor que tiene un objeto de
ese tipo
enum EstadoCivil {soltero, casado,
divorciado};
EstadoCivil ec = EstadoCivil.casado;
ec = EstadoCivil.soltero;
switch(ec)
{
case soltero: System.out.println("Es
soltero");
break;
case casado: System.out.println("Es
casado");
break;
case
divorciado:System.out.println("Es
divorciado");
break;
}
Imports estáticos
Los imports estáticos permiten
importar los elementos estáticos de
una clase, de
forma que para referenciarlos no
tengamos que poner siempre como
prefijo el
nombre de la clase. Por ejemplo,
podemos utilizar las constantes de
color de la
clase java.awt.Color, o bien los
métodos matemáticos de la case Math.
Ejemplo
import static java.awt.Color;
import static java.lang.Math;
public class...
{
...
JLabel lbl = new JLabel();
lbl.setBackground(white); // Antes
sería
Color.white
...
double raiz = sqrt(1252.2); // Antes
sería
Math.sqrt(...)
}
Argumentos variables
Ahora Java permite pasar un número
variable de argumentos a una función
(como
sucede con funciones como printf en
C). Esto se consigue mediante la
expresión
"..." a partir del momento en que
queramos tener un número variable de
argumentos.
Ejemplo
// Funcion que tiene un parámetro
String obligatorio
// y n parámetros int opcionales
public void miFunc(String param,
int... args)
{
...
// Una forma de procesar n
parametros variables
for (int argumento: args)
{
...
}
...
}
...
miFunc("Hola", 1, 20, 30, 2);
miFunc("Adios");
Metainformación
Se tiene la posibilidad de añadir
ciertas anotaciones en campos,
métodos, clases y
otros elementos, que permitan a las
herramientas de desarrollo o de
despliegue
leerlas y realizar ciertas tareas.
Por ejemplo, generar archivos
fuentes, archivos
XML, o un Stub de métodos para
utilizar remotamente con RMI.
Un ejemplo más claro lo tenemos en
las anotaciones que ya se utilizan
para la
herramienta Javadoc. Las marcas
@deprecated no afectan al
comportamiento de
los métodos que las llevan, pero
previenen al compilador para que
muestre una
advertencia indicando que el método
que se utiliza está desaconsejado.
También
se tienen otras marcas @param,
@return, @see, etc., que utiliza
Javadoc para
generar las páginas de documentación
y las relaciones entre ellas.
Ejemplo
// Definición de una interfaz
mediante metainformacion
public @interface MiInterfaz
{
int metodo1();
String metodo2();
}
4. Novedades en librerías
principales
Red
Se han añadido cambios y mejoras
para el trabajo en red, como:
• Soporte para IPv6 en Windows XP y
2003
• Establecimiento de timeouts para
conectar y leer
• API para lanzar aplicaciones RMI a
través de inetd
• La clase InetAddress permite
testear si una URL es alcanzable
(utilidad
ping)
• Otras mejoras en el tratamiento de
cookies, servidores proxy,
tratamiento
de URLs, etc.
Seguridad
Hay bastantes mejoras en seguridad.
Se da soporte a más estándares de
seguridad (SASL, OCSP, TSP, etc.),
hay mejoras en la escalabilidad a
través de
SSLEngine, en criptografía, etc.
Internacionalización
Mediante la internacionalización
podemos construir una aplicación que
se adapte
a varios idiomas, formatos
monetarios, de fecha, etc., sin
tener que reprogramarla.
En este aspecto, se añaden mejoras
en la versión 1.5, relacionadas con:
• La gestión de juegos de caracteres
se basa en el formato Unicode 4.0,
lo
que afecta a las clases Character y
String, entre otras.
• La clase DecimalFormat se ha
modificado para poder procesar
elementos
de tipo BigDecimal o BigInteger sin
perder precisión
• Se han añadido nuevos Locales
soportados, como el vietnamita.
Formateador
La clase Formatter permite dar
formato (justificación y
alineamiento, formatos
numéricos, de fecha, etc.) a las
cadenas y otros tipos de datos,
siguiendo un estilo
parecido al printf de C. También se
permite mediante la interfaz
Formattable dar
formatos (limitados) a tipos creados
por el usuario.
Ejemplo
// Uso de formatter para construir
cadenas formateadas
StringBuilder sb = new
StringBuilder();
Formatter f = new Formatter(sb,
Locale.US);
f.format("Hola, %1$2s, esta es tu
visita numero %2$d", "Pepe",
20);
// Resultaría: "Hola, Pepe, esta es
tu visita numero 20"
// También se tienen unos métodos
predefinidos en ciertas clases
System.out.format("Hola, %1$2s, esta
es tu visita numero %2$d",
"Pepe", 20);
System.err.printf("Hola, %1$2s, esta
es tu visita numero %2$d",
"Pepe", 20);
String s = String.format("Hola,
%1$2s", "Pepe");
Escaneador
La clase Scanner permite parsear un
flujo de entrada (archivo, cadena de
texto,
stream de datos, etc.), y extraer
tokens siguiendo un determinado
patrón o tipo de
datos. También se permite trabajar
con expresiones regulares para
indicar qué
patrones se deben buscar.
Ejemplo
// Lectura de enteros de la entrada
estándar
Scanner sc =
Scanner.create(System.in);
int n = sc.nextInt();
// Lectura de todos los doubles de
un archivo
Scanner sc = Scanner.create(new
File("miFich.txt"));
while (sc.hasNextDouble())
double d = sc.nextDouble();
// Uso de otros delimitadores
String s = "Esto hola es hola 1 hola
ejemplo";
Scanner sc =
Scanner.create(s).useDelimiter("\\s*hola\\s*");
System.out.println(sc.next());
System.out.println(sc.next());
System.out.println(sc.next());
// Sacaría Esto \n es \n 1
Arquitectura de JavaBeans
La arquitectura de JavaBeans se
encuentra dentro del paquete
java.beans. Se ha
añadido una nueva clase,
IndexedPropertyChangeEvent, subclase
de
PropertyChangeEvent, para dar
soporte a eventos que respondan a
cambios en
propiedades indexadas (propiedades
que utilicen un índice para
identificar la parte
del bean que haya cambiado). También
se han añadido mejoras a la hora de
crear
editores de propiedades de beans
(PropertyEditor), como el método
createPropertyEditor(...), y
constructores públicos para la clase
PropertyEditorSupport.
Arquitectura de colecciones
Como se ha comentado antes, las
colecciones (estructura que contiene
clases e
interfaces como Collection, Vector,
ArrayList, etc.) dan soporte a
nuevas
características del lenguaje, como
el autoboxing, mejoras en los Ciclos
(for) , y el
uso de generics. Además, se han
añadido interfaces nuevos, como
Queue,
BlockingQueue y ConcurrentMap, con
algunas implementaciones concretas
de
dichas interfaces. Además, se tienen
nuevas implementaciones de List, Set
y Map.
Manipulación de bits
Los wrappers de tipos simples (es
decir, clases como Integer, Long,
Double, Char)
soportan operaciones de bits, como
highestOneBit, lowestOneBit,
rotateLeft,
rotateRight, reverse, etc.
Elementos matemáticos
El paquete java.math también ha
sufrido modificaciones, como la
adición en la
clase BigDecimal de soporte para
cálculo en coma flotante de
precisión fija.
Clases como Math o StrictMath además
incluyen soporte para senos y
cosenos
hiperbólicos, raíces cúbicas o
logaritmos en base 10. Por último,
también se da
soporte al uso de números
hexadecimales con coma flotante.
Serialización
Además de corregir errores previos
en la serialización, se da soporte
para
serializar el nuevo tipo enum,
aunque la forma de serializarlo
difiere ligeramente
de los tipos tradicionales.
Hilos
Se han añadido los paquetes
java.util.concurrent,
java.util.concurrent.atomic y
java.util.concurrent.locks, que
permiten crear diversas
infraestructuras de hilos,
como pooling de hilos o colas de
bloqueos, liberando al programador
de tener que
controlar todas estas estructuras "a
mano". En definitiva, se da soporte
para
automatizar la programación
concurrente.
Además, a la clase Thread se le han
añadido los métodos getStackTrace y
getAllStackTraces para obtener la
traza de los hilos en un momento
dado.
Monitorización y gestión
Se tienen mejoras en el control o la
monitorización tanto de las
aplicaciones Java
como de la máquina virtual (JVM), a
través de la API de JMX.
5. Novedades en librerías
adicionales
RMI
Se tienen dos mejoras fundamentales
en RMI:
• Generación dinámica de Stubs: se
generan en tiempo de ejecución, sin
necesidad de utilizar rmic
previamente. Sólo tendremos que
utilizarlo para
generar Stubs para clientes que
funcionen con versiones anteriores
de
Java.
• Lanzamiento de rmid o un servidor
RMI Java desde inetd/xinetd.
JDBC
En Java 1.4 se introdujo la interfaz
RowSet, que permitía pasar datos
entre
componentes. En Java 1.5 se han
desarrollado 5 implementaciones de
dicha
interfaz, para cubrir 5 posibles
casos de uso:
• JdbcRowSet: para encapsular un
ResultSet o un driver que utilice
tecnología JDBC
• CachedRowSet: desconecta de la
fuente de datos y trabaja
independientemente, salvo cuando
esté obteniendo datos de dicha
fuente o
volcando datos en ella.
• FilteredRowSet: hereda de la
anterior, y se utiliza para obtener
un
subconjunto de datos
• JoinRowSet: hereda de CachedRowSet
y se emplea para unir múltiples
objetos RowSet.
• WebRowSet: hereda de CachedRowSet
para procesar datos XML.
JNDI
• Mejoras en la clase
javax.naming.NameClassPair para
poder acceder al
nombre completo del servicio de
directorio.
• Soporte para controles estándar de
LDAP
• Soporte para manipular nombres de
LDAP
6. Novedades en la interfaz de
usuario
Internacionalización
Para permitir renderizar texto
| | | | | | |