



























Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Prepara tus exámenes
Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Prepara tus exámenes con los documentos que comparten otros estudiantes como tú en Docsity
Encuentra los documentos específicos para los exámenes de tu universidad
Estudia con lecciones y exámenes resueltos basados en los programas académicos de las mejores universidades
Responde a preguntas de exámenes reales y pon a prueba tu preparación
Consigue puntos base para descargar
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Comunidad
Pide ayuda a la comunidad y resuelve tus dudas de estudio
Ebooks gratuitos
Descarga nuestras guías gratuitas sobre técnicas de estudio, métodos para controlar la ansiedad y consejos para la tesis preparadas por los tutores de Docsity
Aprende Access Fácil. Aprede a crear Formularios tablas Informes todo de la manera mas facil
Tipo: Apuntes
1 / 35
Esta página no es visible en la vista previa
¡No te pierdas las partes importantes!




























Introducción
Antes de empezar
Conceptos Básicos
Características de POO
Contratos
Tipos
Herencia y Composición
Polimorfismo
Bonus Tracks
Como bien se sabe, en Internet existe una basta cantidad contenidos sobre POO, sin embargo, consideramos muy útil que las personas se sienten a revisar, mejorar y generar nuevos contenidos.
Es muy probable que se encuentren definiciones parecidas a las de otras bibliografías, ya que para generar este material consultamos muchos libros y apuntes de facultades y también, a escritores independientes de blogs.
Nuestro objetivo no es lucrar con este libro, sino simplemente devolver algo a la comunidad de desarrollo que tanto nos ha dado.
A lo largo de este libro se muestran diferentes ejemplos de código, los mismos se encuentran en un lenguaje ficticio que decidimos crear por varios motivos.
En primer lugar, para evitar inclinarnos por un lenguaje en particular, buscando con esto no expresar ninguna preferencia por parte de los autores. Por otro lado, también se busca generar abstracciones, sin preocuparnos por las implementaciones de cada lenguaje y mostrar un pseudocódigo que permita hacer foco sobre los conceptos tratados. Finalmente, el utilizar este lenguaje inventado, brinda más flexibilidad para generar los ejemplos.
Confiamos que luego de que el lector entienda los conceptos, busque la forma de implementarlos en el lenguaje que utiliza para trabajar o, simplemente, que es de su agrado.
Existen dos maneras que sugerimos usen para leer este libro.
Antes de empezar 4
A aquellos que se estén iniciando en el paradigma, les sugerimos leer el libro completo y sin saltar capítulos. Ya que para comprender un tema, primero se deben conocer los conceptos que se tocaron secciones anterior.
A los lectores que ya tengan conocimiento sobre la programación orientada a objetos, pueden simplemente consultar los capítulos que contienen los temas que desean ver en particular.
Antes de empezar 5
Garbage Collector : es un mecanismo que se encarga de borrar de la memoria las referencias a objetos y entidades que ya no se usan más, de manera que se pueda maximizar el uso del espacio en memoria.
Destructores : son métodos que se definen para cada objeto y cuyo principal objetivo es liberar los recursos que fueron adquiridos por el objeto a lo largo de su ciclo de vida y romper vínculos con otras entidades que puedan tener referencias a él.
¿Que es un método? ¿Qué diferencia existe con un mensaje?
Un método es la sección de código que se ejecuta al enviar un mensaje. Se identifica con una firma, que es la misma firma del mensaje enviado. Entonces, cuando un objeto recibe un mensaje, se ejecuta un método cuya firma es la misma que la del mensaje.
Ejemplo:
method comer(Tarta tarta){ calorias += tarta.calorias }
La firma de un objeto se define con tres componentes:
Muchos lectores se preguntarán porque no empezamos con la definición de Clase. Esto se debe a que las clases solo son una forma de implementar objetos , pero no son la única manera de hacerlo (como veremos más adelante), por lo que fundamental que no pensemos automaticamente en clases cuando hablamos de objetos. Sin embargo, la mayor parte de los lenguajes de programación que usamos laboral y académicamente usan clases. Por eso vamos a tratarlas en este libro.
¿Qué es una clase? Buena pregunta.
Podemos definir a una clase utilizando dos definiciones complementarias: Una clase es un molde, a partir del cual se crean los objetos. Cuando instanciamos un objeto, el ambiente le pregunta a dicha clase que características y métodos tiene que tener el objeto
Conceptos Básicos 7
que vamos a instanciar.
La otra definición es: Una clase es un ente que determina el comportamiento y el tipo al que pertenecen sus instancias.
Ejemplo de código:
class Persona { public attribute calorias public method comer(Tarta tarta){ self.calorias += tarta.calorias } } class Tarta{ public attribute calorias } class ComidasTests{ method ComerTartaTest (){ var caloriasDespuesDeAlmorzar = 600 Persona alan = new Persona() alan.calorias = 500 Tarta tartaJamonYQueso = new Tarta() tartaJamonYQueso.calorias = 100 alan.comer(tartaJamonYQueso) Assert.AreEqual(caloriasDespuesDeAlmorzar,alan.calorias) } }
La orientación a objetos basada en prototipos es un estilo de reutilización de comportamiento (herencia*) que se logra por medio de la clonación de un objeto ya existente, que sirve como prototipo. Javascript, es el lenguaje orientado a objetos basado en prototipos más conocido.
Así como un objeto puede conocer a otro objeto teniendo una referencia hacia este, también se puede conocer a sí mismo. Cualquier objeto tiene una auto-referencia, denominada this o self (según el lenguaje) para poder mandarse algún mensaje a si mismo.
Conceptos Básicos 8
Los siguientes conceptos que vamos a ver, son características que tiene un buen diseño orientado a objetos, si bien este paradigma no garantiza dichas características, hace mucho más fácil poder lograrlas y en cierta manera nos obliga a usarlas.
La abstracción es la propiedad de los objetos que consiste en tener en cuenta sólo los aspectos más importantes desde un punto de vista determinado y no tener en cuenta otros aspectos. Durante el proceso de abstracción es cuando se decide qué características y comportamientos debe tener el modelo para asi reducir su complejidad. De este modo, las características complejas se hacen más manejables.
Ejemplo:
En POO, podemos considerar una Persona como un objeto que tiene propiedades (como nombre, altura, peso, color de pelo, color de ojos, etcétera) y métodos (como hablar, mirar, andar, correr, parar, etcétera). Gracias a la abstracción, otro objeto Tren puede manipular objetos del tipo Persona sin tener en cuenta sus propiedades ni métodos ya que sólo le interesa, por ejemplo, calcular la cantidad de personas que están viajando en él en ese momento, sin tener en cuenta ninguna otra información relacionada con dichas personas, tales como la altura, el nombre, el color de ojos, etcétera. Nuestro objeto Tren se abstrae de objetos del tipo Persona.
Este concepto hace referencia a que los componentes se deben utilizar como si sólo se conocieran su interfaz y no se tuviera conocimiento de su implementación. En otras palabras, un objeto sabe que otro objeto entiende un determinado mensaje, el cual recibe ciertos parámetros y devuelve algo (o no).
Ejemplo:
Yo como objecto médico quiero saber cuantas cirugías tuvo un paciente, y entonces le envía un mensaje para que el paciente me devuelva el número de cirugías que tuvo. El objeto médico no sabe como devolvió ese número el Paciente, solo sabe que tiene que enviarle el mensaje y recibir un número.
Características de POO 10
Encapsulamiento es la capacidad de diferenciar qué partes de un objeto son parte de la interfaz y cuales permanecerán inaccesibles por el usuario. Son los lenguajes de programación los cuales, por medio los modificadores de acceso, permiten indicar el modo de accesibilidad de un componente.
En POO, a la conjunción de abstracción y ocultamiento de implementación se la llama encapsulamiento.
Según Booch, encapsulamiento “... es el proceso de almacenar en un mismo comportamiento los elementos de una abstracción que constituyen su estructura y su comportamiento; sirve para separar la interfaz contractual de una abstracción y su implementación”.
Veamos si se entiende con un ejemplo:
class Guerrero{ attribute vitalidad } class Monstruo { method atacar(Guerrero barbaro){ barbaro.vitalidad = barbaro.vitalidad - 10 } }
En este caso, el monstruo cuando ataca al guerrero lo debilita, cambiando el valor de la propiedad vitalidad directamente. Obviamente si escribimos una implementación como esta va a funcionar, pero existen diferentes razones por las cuales no nos conviene hacerlo así.
A nivel conceptual, nuestro objeto monstruo, no tiene porque conocer como el bárbaro maneja su vida, este podría hacerlo simplemente con un valor numérico o mismo con otro tipo de objeto. El monstruo solo tiene que mandar el mensaje y es ya cuestión del bárbaro entenderlo y accionar en base a ello.
Viéndolo desde el punto de vista de la escalabilidad y de un lenguaje de programación, si el día de mañana tenemos diferentes objetos que tiene que modificar dicha propiedad, nuestro código se puede volver difícil de cambiar debido a que en varias partes se usar la propiedad vitalidad (por ejemplo supongamos que ahora manejamos la vitalidad con un objeto Vida), si tenemos encapsulado ese comportamiento, solo vamos a tener que hacer un cambio en un solo lado.
Una forma más amigable de hacer esto sería:
Características de POO 11
Estos conceptos no son particulares de POO, pero aun asi se nos olvidan, por eso les vamos a hacer un repaso.
La expresividad tiene que ver con qué tan claro es el código, qué tanto expresa lo que tenías en la cabeza cuando lo escribiste, es decir, que tan bien expresadas están las ideas del programador. Usar variables y métodos con nombres que representan lo que son o hacen, es forma fácil de aplicar expresividad que no tiene nada que ver con el paradigma sino con el programador.
Características de POO 13
Por lo general la declaratividad ayuda a que el código sea más expresivo, porque no se mezcla el algoritmo con lo que querés que haga más a alto nivel. Cuando tenemos un código bien declarativo, podemos entender que es lo que hace sin ver en detalle el algoritmo implementado. Es importante recalcar que la declaratividad es contrario a la imperatividad (osea, detallar linea a linea los pasos que hace el algoritmo).
Entonces, la declaratividad indica que se hace y la expresividad muestra la intención de lo que el código que se va hacer.
Recordemos una frase de Martin Fowler que vale la pena comentar: “ Cuando sientas la necesidad de escribir un comentario, intenta primero refactorizar el código de manera que cualquier comentario se convierte en innecesario. ”
Ejercicio
¿Qué les parece que hace este método?
method ElementoNuevo (var parametro1){ if(parametro1.tipo = “R”){ var numero = coleccion1.count() self.coleccion1[numero +1] = parametro }else{ var numero = coleccion2.count() self.coleccion2[numero +1] = parametro } }
¿Qué les parece que hace este otro método?
method Agregar(Soldado soldado){ if(soldado.esDeReserva()){ self.reservaDeEjercito.Add(soldado) }else{ self.ejercito.Add(soldado) } }
Claramente en el segundo ejemplo se entiende bien que estamos manejando un ejército y que nuestro método quiere agregar un nuevo soldado dependiendo de su tipo al ejército que luchara o al ejército de reserva.
Si tuviésemos que manejar modificar el primer método, tendríamos que hacer un análisis más profundo, revisando en el resto de nuestra aplicación qué significa la letra “R” en el tipo de soldado y para qué sirve la coleccion1 y coleccion2.
Características de POO 14
El diseño por contratos asume que todos los componentes del cliente que invocan una operación en un componente del servidor van a encontrar las precondiciones (y postcondiciones) especificadas como obligatorias para esa operación.
Muchas veces podemos tener algunas cosas para validar en nuestro sistema. Esto es:
Pre-condiciones Post-condiciones Condiciones “permanentes” o invariantes
Por ejemplo, yo siempre que alimente a mi mascota, debo garantizarme que no esté llena. Por lo que quisiera tener algo como:
public class Mascota implements Domesticable { public method alimentarse(){ requires tengoHambre() //ejecutar método } }
Lo mismo puede suceder con las post condiciones, o condiciones que se deben dar en todo momento.
public class Mascota implements Domesticable{ method alimentarse(){ requires tengoHambre() //ejecutar método guarantees estoyLleno() } }
Para hacer cumplir estos contratos, hay 2 maneras:
Contratos 16
Lo importante es que se entienda el concepto del contrato, de ver que yo para poder interactuar de cierta manera con un componente, debo cumplir ciertos requisitos, tanto antes, durante o después de la interacción.
Básicamente, aplican las mismas ideas y conceptos que en la herencia de comportamiento. Las precondiciones, postcondiciones e invariantes se heredan de clase a subclase.
Sin embargo existen algunos condicionamientos, para garantizar el principio de intercambiabilidad. Que se pueden resumir en la siguiente frase:
Require no more, and promise no less
Muy relacionado con la L (Liskov Substitution Principle) de SOLID, la cual plantea que donde uso una clase, debería poder usar cualquier subclase de ella y que siga funcionando todo correctamente.
Contratos 17
Explícito, estático y nominal Implícito y dinámico
Es un mecanismo utilizado en los lenguajes de chequeo estático, por el cual nosotros le “aseguramos” al compilador que cierto objeto pertenece al tipo especificado.
Ejemplo:
//Suponemos que los métodos de la API siempre reciben un Object method recibirPerroDeApi(Object obj){ var perro = (Perro) obj perro.ladrar() }
Hay que ser muy cuidadosos al usar el casteo, porque podría llevar a “confundir” al compilador y hacer que rompa en tiempo de ejecución (perdiendo el beneficio que nos da el chequeo estático), por ejemplo si en Object que se recibe es un Gato en vez de un perro, al llamar al método "ladrar" nuestro programa lanzará una excepción.
Tipos 19
La sobrecarga es la capacidad de un lenguaje de programación, que permite nombrar con el mismo identificador diferentes variables u operaciones.
La sobrecarga de métodos se refiere a la posibilidad de tener dos o más métodos con el mismo nombre pero diferente firma. El compilador usará una u otra dependiendo de los parámetros usados.
El mismo método dentro de una clase permite hacer cosas distintas en función de los parámetros.
Ejemplo
class Articulo { private attribute precio public method setPrecio() { precio = 3. } public method setPrecio(Currency nuevoPrecio) { precio = nuevoPrecio } }
En este ejemplo que vemos, uno podría invocar al método "setPrecio" enviando un precio o sin parámetros, dependiendo como se invoque en nuestro código, el compilador decidirá si llama a la primer implementación o a la segunda.
En tiempo de compilación, se buscan todas las llamadas a este método y según el tipo de los parámetros con los que se esté invocando y el objeto que puede o no devolver (necesariamente son lenguajes de chequeo estático), se determina a qué implementación llamará. Si la combinación de parámetros no es excluyente, el compilador falla.
Los multimethods, a diferencia de la sobrecarga, son un conjunto de métodos con la misma firma, pero que se pueden solapar, y se decide cuál ejecutar en tiempo de ejecución.
Herencia y Composición 20