Hoy hablamos de: - Diagramas de clases Ā Ā Ā Hablamos de como dibujar una clase, con su nombre, atributos y mĆ©todos. Ā Ā Ā Hablamos de como escribir un mĆ©todo de clase y una variable de clase (poniĆ©ndoles una '(C)' al lado) Ā Ā Ā Hablamos de como relacionar las clases.Ā Son importantes las flechas y la cardinalidad. Ā Ā Ā ĀæQuĆ© pasa si hay una cajita sin mĆ©todos? Quiere decir que las instancias de esa clase no entienden ningun mensaje.... Eso nos indica algo malo. - Responsabilidad y delegación, con el ejercicio de trenes y vagones: ĀæQuĆ© objetos tienen que tener quĆ© responsabilidad?Ā Necesitabamos obtener la cantidad de pasajeros para una formación determinada.Ā Para ello, le dimos la responsabilidad de darnos dicho nĆŗmero a las formaciones.Ā En un workspace: formacion cantidadDePasajeros ĀæPor quĆ© a las formaciones y no a los depósitos o a la boleterĆa?Ā La formaciones no hablan... Porque nosotros estamos haciendo un modelo... La formación que programamos no necesariamente es la formación de posta.Ā Le damos la responsabilidad a las formaciones porque suena natural hacerlo asĆ.Ā Si queremos saber la cantidad de pasajeros de una formación, se lo preguntamos a la formación. Entonces empezamos a escribir el mĆ©todo que resuelva eso: Formacion>> cantidadDePasajeros Ā ^( self vagones collect: [:vagon | vagon cantidadDePasajeros] ) sum. Ā Decidimos tener toooodos los vagones en una sola colección.Ā Eso nos obliga a tratarlos todos polimorficamente, sean de carga o de pasajeros. Ahora necesitamos modelar a los vagones, porque tienen que entender el mensaje cantidadDePasajeros.Ā Y tenemos varios tipos de vagones: de pasajeros y de carga. VagonDePasajeros>> cantidadDePasajeros Ā Ā Ā ^metrosDeAncho <= 2.5 Ā Ā Ā ifTrue: [ metrosDeLargo * 8 ] Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā ifFalse: [ metrosDeLargo * 10 ] VagonDeCarga>> cantidadDePasajeros Ā Ā Ā "Un vagon de carga no lleva pasajeros, entiende este mensaje para ser polimorfico con los vagones de pasajeros" Ā Ā Ā ^0 Ā Ā Ā -------------- Ahora completemos elĀ workspace: formacionCorta := Formacion new. vagonPasajeros1 := VagonDePasajeros new. vagonPasajeros1 metrosDeAncho: 2. vagonPasajeros1 metrosDeLargo: 10. vagonPasajeros2 := VagonDePasajeros new. vagonPasajeros1 metrosDeAncho: 3. vagonPasajeros1 metrosDeLargo: 10. vagonCarga := VagonDeCarga new. formacionCorta agregaVagon: vagonPasajeros1. formacionCorta agregaVagon: vagonPasajeros2. formacionCorta agregaVagon: vagonCarga. --------------------- Hay algo feo aca... :S.Ā Cada vez que creamos un vagon de pasajeros, nos tenemos que acordar de agregarle sus metros de ancho y sus metros de largo!Ā Fua, si tenemos que crear 30... nos vamos a equivocar seguro.Ā EstarĆa reee bueno tener un objeto al que pueda decirle "che, dame un vagon de carga de 2 de ancho y 10 de largo" onda: objetoQueMeVaAConstruirVagones dameUnNuevoVagonConAncho: 2 yLargo: 10 ĀæPero quĆ© objeto? Y.. hasta ahora el que tenia la responsabilidad de crearme los vagones de pasajeros era la clase VagonDePasajeros.Ā Demosle entonces la responsabilidad nueva tambiĆ©n!! Y asĆ reemplazamos vagonPasajeros1 := VagonDePasajeros dameUnNuevoVagonConAncho: 2 yLargo: 10 vagonPasajeros2 := VagonDePasajeros dameUnNuevoVagonConAncho: 3 yLargo: 10 ĀæY ese mĆ©todo como se escribe en smalltalk, donde lo meto? Clase VagonDePasajeros >> dameUnNuevoVagonConAncho: ancho yLargo: largo Ā Ā Ā | vagon | Ā Ā Ā vagon :=self new. Ā Ā Ā Ā vagon ancho: ancho. Ā Ā Ā vagon largo: largo. Ā Ā Ā ^vagon Ā Ā Ā Ese mĆ©todo que escribimos en la parte de "clase", que se va a ejecutar cuando le mandemos un mensaje a la clase, se llama mĆ©todo de clase. --------------------- Ahora encaremos el segundo punto.Ā Saber la cantidad de vagones livianos de una formación. ĀæA quien le damos esa responsabilidad? Y... suena lógico dĆ”rsela a la formación, porque es ella quien conoce a los vagones.Ā Esta bueno ver como ahora la responsabilidad surgió a partir de las responsabilidades que ya tenĆan nuestros objetos.Ā Como una formación ya conoce a sus vagones, entonces le damos la responsabilidad de filtrar los livianos a ella.Ā AsĆ tambiĆ©n respetamos el encapsulamiento, haciendo que la Ćŗnica responsable de trabajar con la coleccion de vagones de una formación sea esa misma formación. Ahora aca tenemos 2 variantes: 1) Formacion>> cantidadVagonesLivianos Ā Ā Ā ^( vagones select:[:v | v pesoMaximo <= 2500 ] ) size. 2) Formacion>> cantidadVagonesLivianos Ā Ā Ā ^( vagones select:[:v | v esLiviano ] ) size. Ā Ā Ā Recalcamos ambas versiones, porque es necesario contar que la primera tiene varios problemas:Ā no respeta en encapsulamiento, estĆ” tomando responsabilidades que le pertenecen a los vagones, me impide usar polimorfismo (si tuviera vagones que calculan la liviandad de distinta manera), y fomenta la repetición de código. En cambio, en la segunda es mĆ”s sencilla definir la liviandad distinta para cada tipo de vagón, sin que nos interese como se decide eso. Entonces: Version 1) :( Version 2) :D Ahora pasemos a escribir el mĆ©todo esLiviano en los vagones: VagonPasajeros>>esLiviano Ā Ā Ā ^self pesoMaximo <= 2500 Ā Ā Ā Ā Ā Ā >>pesoMaximo Ā Ā Ā Ā Ā Ā ^self cantidadTotalPasajeros * 80 Ā Ā Ā VagonCarga>>esLiviano Ā Ā Ā ^self pesoMaximo <= 2500 Ā Ā Ā Ā Ā Ā >>pesoMaximo Ā Ā Ā Ā Ā Ā ^self cargaMaxima + 160 Ā Ā Ā Ā Ā Ā PEROOOOOO, ”””Estamos repitiendo código!!!Ā Lamentablemente, les vamos a pedir que compren eso hasta la semana que viene.Ā AhĆ vamos a resolver este problema con una herramienta nueva.Ā Aunque si quieren, pueden pensar como se resolvĆa ese problema con el object browser, con clones y prototipos (porque lo que vamos a ver la semana que viene tiene una mecĆ”nica parecida). Ahora que tenemos resuelto el punto 2, encontramos que hay un par de nĆŗmeros mĆ”gicos.Ā "MĆ”gicos" porque no sabemos de donde provienen.Ā Por ejemplo el 2500, el 160, el 80.Ā Ok, en el enunciado lo dice, pero no en el código...Ā Podemos buscar de reemplazarlos por algo mĆ”s feliz. PodrĆamos usar una variable que contenga esos valores.Ā Por ejemplo: - limiteDeLiviandad para el 2500 - pesoPersona para el 80 - el 160 podrĆamos reemplazarlo por (pesoPersona * 2) Pero si son variables de instancia, me deberĆa ocupar de cargarlas en cada instancia, cosa que puede ser engorroso... Antes, cuando tenĆamos código repĆ©tido, lo subĆamos a la clase.Ā ĀæPor quĆ© ahora que tenemos variables con valores repetidos no lo subimos a la clase tambiĆ©n? Ese concepto de tener una variable en la clase, vamos a llamarlo variable de clase, y tiene la particularidad que es una variable compartida por todas las instancias. ĀæQuiĆ©n tiene la responsabilidad de setear esa variable? La clase... que lo haga una instancia es medio chancho.Ā AcuerdensĆ© del encapsulamiento.Ā Con las clases tambiĆ©n juega.Ā ĀæY como lo hace una clase?Ā A travĆ©s de un mĆ©todo de clase :). Cosas a tener en cuenta: Ā Ā Ā -si asigno la variable de clase, cambia la referencia para todas las instancias. Ā Ā Ā -las variables de clase empiezan en mayĆŗsculas. Ā Ā Ā -las instancias pueden acceder directamente a las variables de su clase Ā Ā Ā Entonces el código queda: VagonPasajeros(vc LimiteLiviandad, PesoPersona) Ā Ā Ā >>esLiviano Ā Ā Ā Ā Ā Ā ^self pesoMaximo <= LimiteLiviandad Ā Ā Ā Ā Ā Ā >>pesoMaximo Ā Ā Ā Ā Ā Ā ^self cantidadTotalPasajeros * PesoPersona Ā Ā Ā VagonCarga(vc LimiteLiviandad, PesoPersona, CantidadGuardas) Ā Ā Ā >>esLiviano Ā Ā Ā Ā Ā Ā ^self pesoMaximo <= LimiteLiviandad Ā Ā Ā Ā Ā Ā >>pesoMaximo Ā Ā Ā Ā Ā Ā ^self cargaMaxima + self pesoGuardas Ā Ā Ā Ā Ā Ā >>pesoGuardas Ā Ā Ā Ā Ā Ā ^PesoPersona * CantidadGuardas - Tarea: Tienen que traer hecho en mĆ”quina e impreso para la clase que viene (dentro de 3 semanas) en smalltalk el siguiente ejercicio.Ā El mismo tiene que contener: Ā - Código Ā - Workspace Ā - Diagrama de clases (pueden hacerlo en Visio o en alguna otra herramienta como ArgoUML, StarUML o yuml) |
Cursosā > āmiercoles-Objetosā > ā