4 - Paradigma Orientado A Objeto
4 - Paradigma Orientado A Objeto
4 - Paradigma Orientado A Objeto
Hasta acá aprendimos que hay diferentes paradigmas para programar y repasamos el paradigma más conocido que es el Estructurado.
Ahora vamos a cambiar de paradigma y para eso necesitamos estar con la mente muy abierta para poder pensar distinto. En esta
unidad vamos a ver el Paradigma orientado a Objetos. Este paradigma es uno de los más utilizados hoy en día.
En este paradigma, la abstracción principal son los objetos. Un objeto es algo que puede representar una idea abstracta o una entidad
concreta del mundo real. Por ejemplo, si nos dicen la palabra Auto, cada uno va a imaginarse un auto diferente, pero podemos coincidir
en que un auto es un vehículo, que tiene un volante, color, puertas, luces, etc. todo esto que hace al auto son sus atributos. Además,
ese auto sabe hacer cosas: frenar, acelerar, poner en marcha, abrir el capot, etc.: eso que el auto sabe hacer son sus métodos. Al
momento de representar el auto en un sistema, no vamos a agregar todos sus atributos ni todos sus métodos porque serían cientos o
miles. Por el contrario, vamos a agregar solamente aquellos que sean representativos y útiles para el problema a resolver. Por este
motivo, esto resulta ser una abstracción.
Este ejemplo fue sobre un objeto concreto del mundo real, pero dijimos que también podemos pensar como objetos a ideas o conceptos
abstractos. Es el caso, por ejemplo, de una deuda, una cadena de caracteres, una compra, etc., cada uno de estos puede ser un objeto
en un sistema de este paradigma.
Debido a la importancia que tienen los objetos en este paradigma, un programa es entendido como un conjunto de objetos que
intercambian mensajes para alcanzar determinado objetivo.
Para que estos objetos se puedan enviar mensajes tienen que conocerse y eso se logra a través de una variable. La variable es el
nombre con el que llamamos a ese objeto. Volvamos al ejemplo del auto.
Yo soy la dueña de un auto que llamo autoDeNadia. Cuando modelo el arranque del auto en un sistema le tengo que
mandar un mensaje para que haga lo que yo quiero. Eso se vería así:
autoDeNadia.PonerEnMarcha();
autoDeNadia.Acelerar();
autoDeNadia dijimos que es el nombre (la variable) que tiene ese objeto. Y lo que viene después del punto es el mensaje
que le estoy enviando.
O de manera genérica:
En este último gráfico aparece la Clase. Más adelante, veremos de qué se trata.
Mensaje
Ahora bien, hablamos del mensaje Acelerar y del método Acelerar ¿Cuál es la diferencia entre mensaje y método?El mensaje es lo que
le envía un objeto emisor a otro receptor. El método es cómo ese objeto receptor implementa ese mensaje. Dicho de otra manera. El
objeto Médico le manda un mensaje al objeto Kinesiólogo para que le haga láser a un paciente. El objeto Médico sabe lo que le puede
pedir al Kinesiólogo y le manda un mensaje para que lo haga, pero el que lo sabe hacer es el objeto Kinesiólogo. Es decir que, el objeto
kinesiólogo tiene un método que es el paso a paso de cómo aplicarle láser a un paciente. Volviendo al mundo de la programación, el
objeto emisor solo conoce el nombre del mensaje, pero no sabe cómo se resuelve. El método es la porción de código que tiene el objeto
receptor y que resuelve ese mensaje.
Interfaz
Agreguemos un concepto más que es el de la interfaz. La interfaz es todo lo que el objeto publica (los mensajes que le puedo enviar)
para otro objeto lo use.
Para que un objeto le pueda mandar un mensaje a otro, lo tiene que conocer, y lo conoce a través de una Referencia. El conjunto de
referencias que tiene un objeto representa su estado. Esas referencias son unidireccionales. Es decir, si Juan conoce a Pedro, no
implica que Pedro conozca a Juan. Si queremos que la relación sea bidireccional, debería haber una referencia de Juan a Pedro y otra
de Pedro a Juan.
Ya sabemos modelar gráficamente nuestro auto, pero ¿Cómo se vería eso en código? Eso depende del lenguaje en el que lo
implementemos. Algunos lenguajes que soportan la Programación Orientada a Objetos (POO) son Java, Smalltalk y Wollok (vamos a
usar una sintaxis similar a este último).
Vamos a hacer un ejemplo genérico:
object autoDeNadia {
var puertas = 5
var color = “rojo”
var ABS = True
var velocidad = 50
method frenar() {
velocidad = velocidad - 10
}
method acelerar(cantidad) {
velocidad = velocidad + cantidad
}
}
Observar que object autoDeNadia: define un nuevo objeto de nombre autoDeNadia. Entre llaves tiene sus atributos y métodos.
Tal como vimos en el primer componente, en la sección Esquema de Tipado, puede ser que en algunos lenguajes el código se vea
diferente puesto que tienen que definir tipos para los parámetros y métodos.
Es una buena práctica que los valores de los atributos solo sean modificados por el mismo objeto, es decir que nadie “de afuera” venga
a cambiar el valor de la velocidad o la cantidad de puertas si no lo hace a través de los métodos que tiene definidos el autoDeNadia. Es
por eso que hay que definir los Accessors que son los métodos que permiten leer (getter) y escribir (setter) esos valores. Eso se logra
agregando estos métodos al auto:
// getter
method velocidad() { return velocidad }
// setter
method velocidad(_velocidad) { velocidad = _velocidad }
Lo mismo habría que hacer para las puertas y el resto de los atributos que se quieran modificar.
UML
Antes de continuar con el tema de objetos vamos a hacer una pausa para ver cómo se comunican los diseños hechos bajo este
paradigma. En el paradigma estructurado, cuando teníamos que representar un algoritmo de forma visual lo hacíamos a través de un
diagrama de flujo. Pero en el mundo de los objetos eso no sería útil porque no hay una única estructura de control, por el contrario, son
varios objetos conviviendo en un ambiente que se mandan mensajes constantemente. Entonces ¿Cómo lo representamos?
UML es un Lenguaje Unificado de Modelado que permite comunicar el análisis y el diseño de los sistemas. Para esto cuenta con
distintos tipos de diagramas dependiendo de los que se quiera comunicar. Esos diagramas son:
Para este componente, vamos a utilizar el diagrama de objetos, de clase y de secuencia, pero muy a alto nivel. No entraremos en
detalle en cada uno de ellos porque no nos interesa aprender cómo se documenta, solo nos interesa ejemplificar cómo se diseña en el
paradigma orientado a objetos. De todas formas, los diagramas son muy intuitivos de modo que, sin demasiada explicación, los va a
entender. Por ejemplo, la representación del objeto que mencionamos en el ítem anterior, es parte de cómo UML modela los objetos.
Más adelante cuando hablemos de clases, vamos a usar una parte del diagrama de clases de UML. Si se quiere aprenderlos más en
detalle sugerimos que se lea el libro UML en 24 horas que se puede encontrar como parte de la bibliografía opcional de este
componente.
Respecto del diagrama de secuencia, nos sirve para modelar la interacción de los objetos a través del envío del mensaje. El diagrama
de secuencia se ve de esta forma:
A grandes rasgos, sería: arriba, encuadrados, van los objetos, cada uno con su línea de vida, y en el medio, la secuencia de mensajes
que se envían. Este diagrama nos va a servir más adelante para realizar los ejercicios.
Igualdad e identidad
Dijimos que en este paradigma un programa se va a ver como un conjunto de objetos que se envían mensajes. De modo que vamos a
tener muchos objetos conviviendo simultáneamente. Incluso, muchos objetos que pueden ser parecidos. Por ejemplo, puede ser que el
autoDeLeo también tenga 5 puertas y una velocidad de 50 como el autoDeNadia. ¿Pero esos objetos son idénticos? No, esos objetos
son iguales porque tienen los mismos valores de sus atributos. Sin embargo, el autoDeNadia solo es idéntico a sí mismo. Es importante
tener en clara esta diferencia entre identidad e igualdad.
Polimorfismo
El concepto de polimorfismo es muy importante en este paradigma. A grandes rasgos, consiste en que un objeto emisor pueda enviarle
un mismo mensaje a diferentes objetos y esos objetos pueden responderlo, aun cuando lo implementen de una manera diferente.
Lectura Optativa
Para que quede más claro el concepto los invitamos a leer esta bibliografía (página 3 a 6)
Colecciones
Otro concepto muy importante de este paradigma son las colecciones. Una colección es un conjunto de elementos relacionados que no
necesariamente son del mismo tipo. Por ejemplo, la lista del supermercado, el menú de comidas de un restaurant, las cosas que hay en
la caja de herramientas, etc. Las colecciones nos permiten modelar las relaciones uno a mucho.
Para comprender mejor este concepto y ver algunos ejemplos de implementación los invitamos a continuar leyendo las páginas 9 a 18
del apunte.
Clases
Supónganse que tenemos que modelar al viejo y querido videoclub que tiene películas para alquilar y vender. Cada película es distinta
porque tiene título, banda sonora, director, protagonistas, etc.; además, cuando se las quiera comprar, cada una va a tener su precio. Si
quisiéramos saberlo, se lo pediríamos así:
miPobreAngelito.precio();
nuncaMeDejesSola.precio();
tesisDeUnHomicidio.precio();
object miPobreAngelito {
var precio
// getter
method precio() = precio
// setter
method precio(_precio) { precio = _precio }
}
Y el resto serían exactamente igual, pero con otro nombre. Supónganse que además de darme el precio puedan decirme si está
alquilada o no, contarme la trama, etc.; tendríamos esos métodos en cada uno de los objetos. Para no generar código duplicado (o
triplicado en este caso), lo que hacemos es crear una clase. Una clase es un molde a partir del cual luego se crean esos objetos. Esto
permite definir por única vez el comportamiento de la clase película y a partir de ahí crear películas.
class Pelicula {
var precio
// getter
method precio() = precio
// setter
method precio(_precio) { precio = _precio }
}
Observen que la clase se define como class y no como object. Además, el nombre de la clase empieza en mayúsculas en lugar de
hacerlo en minúsculas como hacíamos con los objetos.
La definición que escribimos al principio de cada objeto película (object miPobreAngelito ) ya deja de tener sentido porque ahora
tenemos la clase Película. Dijimos que la clase era un molde, con ese molde podemos generar lo que llamamos Instancias. Vamos a
generar la instancia miPobreAngelito de la clase Película.
const miPobreAngelito = new Pelicula()
miPobreAngelito, al ser una instancia de la clase Pelicula va a tener sus atributos y métodos. Entonces voy a poder
asignarle un precio:
miPobreAngelito.precio(180)
y preguntarle cuá l es su precio:
miPobreAngelito.precio()
Esto mismo hay que hacer para el resto de las películas que sea quiera crear. Cada vez que modifico el precio, estoy modificando el
precio de esa instancia en particular. Por eso a la variable precio se la llama variable de instancia.
El precio del poster va a ser el precio del material multiplicado por su alto y su ancho.
class Poster {
var ancho
var alto
var material
// getter
method ancho() = ancho
// setter
method ancho(_ancho) { ancho = _ancho }
// getter
method alto() = alto
// setter
method alto(_alto) { alto = _alto}
method precio() = alto * ancho * material.precio()
}
class Material
{
var precio
// getter
method precio() = precio
// setter
method precio(_precio) { precio = _precio }
}
const esperandoLaCarroza = new Poster()
esperandoLaCarroza.precio();
miPobreAngelito.precio();
son dos clases diferentes (una Poster y una Película) que saben responder (y resuelven de manera diferente) el precio. Los objetos
esperandoLaCarroza y miPobreAngelito son polimórficos a pesar de ser de clases diferentes.
Herencia y Superclase
Volviendo al ejemplo del auto, supongamos que tengo una clase Auto para poder crear muchos autos que sepan poner en marcha,
acelerar, frenar y abrir el capot como habíamos dicho. Pero también quiero modelar la clase moto que sabe poner en marcha, acelerar y
frenar. Y la bicicleta que sabe acelerar y frenar. Si bien cada uno de estos acelera y frena distinto, está claro que todos saben hacerlo.
De modo que son polimórficos. Sin embargo, hay cosas que un auto sabe hacer y una moto no, de modo que no podrían construirse
desde la misma clase. Pero lo que sí se puede hacer es agregar el comportamiento común en lo que llamamos una superclase. Se dice
que las otras clases heredan de la superclasae (Vehículo) y se representa en un diagrama de clases de UML de esta manera:
Material de lectura
En la siguiente lectura vamos a aprender sobre superclases y herencia:
Se requiere un sistema para un campo en el que hay que atender a los animales, que tienen varias necesidades. De todos los animales
posibles, nos pidieron que consideremos solamente a las vacas, gallinas y cerdos, que tienen estas características.
Vaca
Cerdo
Cuando come aumenta el peso en lo que comió – 200 g (si come menos de 200 gr. no aumenta nada); si come más de 1 kg se le va el
hambre, de lo contrario, no.
Quiero saber, para cada cerdo, cuánto comió la vez que más comió.
Siempre conviene vacunarlo.
Cuando bebe se le va la sed, y le da hambre.
Si come más de tres veces sin beber le da sed.
Gallina
Se pide:
2. Escribir en pseudocódigo por lo menos dos métodos que no sean los Accesors.
Propuesta
para el aula
Sugerimos plantear una situación cotidiana que pueda modelarse con el Paradigma orientado a Objetos, para
que luego sea trabajada en el aula con el grupo de estudiantes. Planteada la consigna a los alumnos sugerimos:
Pedirles a los alumnos que trabajen en grupos pensando los objetos intervinientes y sus respectivos
atributos y métodos.
Solicitarles que armen un diagrama de secuencia.
Posteriormente debatan en clase las soluciones propuestas y los niveles de abstracción logrados.
Les proponemos pensar en: los errores cometidos, cómo ocurrieron y a qué se debieron, las estrategias que
surgieron para corregirlos, tanto del docente como del alumno, la complejidad que tuvo la tarea, el tipo de
intercambio que se dio entre los alumnos a partir de la consigna, entre otros.