class: center, middle, inverse, title-slide # Repaso POO
### Licenciatura en Ciencias Genómicas, UNAM ### First version: 2021-08-15; Last update: 2021-08-30 --- <style type="text/css"> /* From https://github.com/yihui/xaringan/issues/147 */ .scroll-output { height: 80%; overflow-y: scroll; } /* https://stac koverflow.com/questions/50919104/horizontally-scrollable-output-on-xaringan-slides */ pre { max-width: 100%; overflow-x: scroll; } </style> # Clases y objetos * Clase: - ejemplo: * Objeto: - ejemplo: * Atributo: - ejemplo: * Método: - ejemplo --- # Clases y objetos * **Clase**: Entidad que define una serie de elementos que determinan un estado (atributos) y un comportamiento (método). Plantillas de los objetos. * **Objeto**: Instancia de una clase. <img src="imgs/clase_1/ej_clase_objeto.png" width="450px" style="display: block; margin: auto;" /> --- <img src="imgs/clase_1/ej_clase_objeto2.png" width="800px" style="display: block; margin: auto;" /> --- # Nuestro problema... Tenemos varios animales, y queremos representarlos en el código. ¿Qué clase pondrían?¿Cuáles serían los objetos? <img src="imgs/clase_1/pregunta1.png" width="600px" style="display: block; margin: auto;" /> --- <img src="imgs/clase_1/mamifero.png" width="600px" style="display: block; margin: auto;" /> --- Además, los mamíferos tienen subcategorías <img src="imgs/clase_1/car_clases_mamifero.png" width="1000px" style="display: block; margin: auto;" /> --- Y teniendo estas subcategorías, ya podemos meter a nuestros animales en cada una. Nuestros objetos ya pueden surgir de clases específicas para ellos. <img src="imgs/clase_1/objetos_mamiferos.png" width="1000px" style="display: block; margin: auto;" /> --- # Definimos una clase y atributos ```python class mamifero(): # Atributos de clase ``` --- # Definimos una clase y atributos ```python class mamifero(): # Atributos de clase vertebrado : True pelo : True # Atributos de instancia ``` --- # Definimos una clase y atributos ```python class mamifero(): # Atributos de clase vertebrado : True pelo : True # Atributos de instancia alimentacion: '' tamanho: None peso: None progenie: 0 ``` -- ```python perro = mamifero() perro.vertebrado ``` -- Sin pensar todavía en constructores, ¿qué problema ven en este código? --- ## Agregamos métodos *self*: variable para referirnos a un objeto dentro del método ```python class mamifero(): #... # Atributos de instancia alimentacion = '' # carnívoro, omnívoro, etc # ... ``` --- ## Agregamos métodos *self*: variable para referirnos a un objeto dentro del método ```python class mamifero(): #... # Atributos de instancia alimentacion = '' # carnívoro, omnívoro, etc # ... # Cuántos puede tener y cuántos van a sobrevivir def reproducirse(self, max_progenie): self.progenie += choice(range( max_progenie)) def crecer(self, crecimiento): self.altura += crecimiento self.peso += crecimiento * 0.4 ``` -- ```python perro = mamifero() perro.alimentacion ``` ``` ## '' ``` --- ## Probamos nuestros métodos ```python perro.alimentacion = 'omnivoro' perro.alimentacion ``` ``` ## 'omnivoro' ``` ```python perro.altura = 43 perro.peso = 6.1 perro.progenie ``` ``` ## 0 ``` ```python perro.reproducirse(6) perro.progenie ``` ``` ## 2 ``` --- # <span style="color:Plum">Ejercicio 1</span> #### <span style="color:Orchid">Clase, atributos y métodos</span> * Crea la clase **animal** y agrega los atributos **nombre** y **edad**. También crea un método llamado **haz_ruido** que imprima "AAAAAAAAAAAAH".  --- ## Constructores ```python class mamifero(): # Atributos de clase # ... def __init__(alimentacion, altura, peso, progenie=0): # Atributos de instancia self.alimentacion = alimentacion # carnívoro, omnívoro, etc self.altura = altura #cm self.peso = peso #kg self.progenie = progenie # Cuántos puede tener y cuántos van a sobrevivir def reproducirse(self, max_progenie): self.progenie += choice(range( max_progenie)) #... ``` ```python perro = mamifero("omnívoro", 43, 6.1) ``` -- ¿Qué problema hay con el constructor? --- ```python perro = mamifero("omnívoro", 43, 6.1) perro.__dict__ ``` ``` ## {'alimentacion': 'omnívoro', 'altura': 43, 'peso': 6.1, 'progenie': 0} ``` --- # <span style="color:Plum">Ejercicio 2</span> #### <span style="color:Orchid">Contructor</span> * Agreguen un constructor a su clase animal --- # Herencia -- Mecanismo por el cual una clase se deriva de otra de manera que extiende su funcionalidad. Al derivarse de una clase, **hereda** sus métodos y atributos. <img src="imgs/clase_1/ej_herencia.png" width="600px" style="display: block; margin: auto;" /> --- # Superclase y subclase -- La clase **de la que estamos heredando** se suele denominar clase base, clase padre, *superclase*, etc. La clase que recibe la **herencia** es la *subclase*. <img src="imgs/clase_1/ej_herencia.png" width="600px" style="display: block; margin: auto;" /> --- # Herencia y superclase Si también necesitáramos una clase `monotrema` (mamíferos que ponen huevos), podemos crear esta nueva clase **heredando** los atributos y métodos de la clase `mamifero`, la cual se convertiría en una *super*clase. ```python class monotrema(mamifero): espolon = True def poner_huevo(self, max_huevos): huevos = 0 # Cuántos de esos huevos eclosionan for n in range(max_huevos): if choice([True, False]): huevos += 1 if huevos>0: self.reproducirse(huevos) ``` --- ```python echidna = monotrema("carnívoro", 50, 6) echidna.__dict__ ``` ``` ## {'alimentacion': 'carnívoro', 'altura': 50, 'peso': 6, 'progenie': 0} ``` ```python echidna.crecer(10) echidna.__dict__ ``` ``` ## {'alimentacion': 'carnívoro', 'altura': 60, 'peso': 10.0, 'progenie': 0} ``` ```python echidna.poner_huevo(5) echidna.progenie ``` ``` ## 2 ``` **Heredamos los métodos y los atributos** --- # <span style="color:Plum">Ejercicio 3</span> #### <span style="color:Orchid">Herencia y superclase</span> * Crea la clase **perro** y la clase **gato** de manera que <span style="color:Brown">**hereden**</span> la clase **animal** * A la clase gato agrégale el atributo **usa_arenero** --- # Overriding -- Overriding (podemos verlo como **sobreescribir o anular**) es una característica que permite que una subclase implemente a su manera un método que heredó de una superclase. <img src="imgs/clase_1/ej_overriding.png" width="800px" style="display: block; margin: auto;" /> --- # Overriding Si ahora queremos una clase de mamíferos `placentarios` y queremos guardar la información de si son acuáticos y además si crecen aumentan más su peso. ```python from random import choice, seed class placentario(mamifero): def __init__(self, alimentacion, altura, peso, acuatico, progenie=0): self.acuatico = acuatico def crecer(self, crecimiento): self.altura += crecimiento self.peso += crecimiento * 2 ``` ```python cachalote = placentario('carnívoro', 200, 41*10**3, True ) cachalote.alimentacion ``` -- ¿Qué le falta a éste código? --- ```python cachalote = placentario('carnívoro', 200, 41*10**3, True ) cachalote.__dict__ ``` ``` ## {'alimentacion': 'carnívoro', 'altura': 200, 'peso': 41000, 'progenie': 0, 'acuatico': True} ``` --- # <span style="color:Plum">Ejercicio 4</span> #### <span style="color:Orchid">Overriding</span> * Haz que la clase **perro** haga un <span style="color:Brown">overriding</span> del método **haz_ruido** para que ahora diga "guau" o su onomatopeya favorita --- # Polimorfismos -- Al invocar un método con el mismo nombre en distintos objetos obtendremos una respuesta distinta. <img src="imgs/clase_1/ej_polimorfismo.png" width="800px" style="display: block; margin: auto;" /> --- # Polimorfismos Tenemos una nueva clase marsupial, que igual crece y cambia su peso de manera distinta. Podemos usar ambos métodos sin problema ```python from random import choice, seed class marsupial(mamifero): def crecer(self, crecimiento): self.altura += crecimiento self.peso += crecimiento * 0.7 ``` ```python cachalote = placentario('carnívoro', 200, 41*10**3, True ) tlacuache = marsupial('omnívoro', 30, 1.2) for mamiferito in [cachalote, tlacuache]: mamiferito.crecer(10) cachalote.peso, tlacuache.peso ``` ``` ## (41020, 8.2) ``` --- # <span style="color:Plum">Ejercicio 5</span> #### <span style="color:Orchid">Polimorfismo</span> * Haz que la clase **gato** haga un <span style="color:Brown">polimorfismo</span> del método **haz_ruido** para que ahora diga "miau" o su onomatopeya favorita --- # <span style="color:CadetBlue">Ejercicio completo</span> <img src="imgs/clase_1/ejercicio_final.png" width="600px" style="display: block; margin: auto;" /> --- # <span style="color:CadetBlue">Ejercicio completo</span> Utilizando esta *superclase* animal, crea otras dos clases, perro y gato. Ambos van a hacer un **override** de haz_ruido() con sus respectivos sonidos (guau, miau, o con su onomatopeya favorita). También agreguen el atributo "usa_arenero" en la clase gato. Al final, creen 2 objetos, un perro y un gato con los cuales llamen a la función *haz_ruido()* y a '__dict__' --- # Pasos del ejercicio 1.- Crear la clase perro y la clase gato, heredando la clase animal. 2.- Sobreescribe (**override**) la función *haz_ruido()* en la clase perro y gato para que cada uno haga el sonido correcto. 3.- Agrega el atributo "usa_arenero" para la clase gato (**override**). 4.- Crea un objeto gato y un objeto perro con sus respectivos atributos y haz que ambos hagan sus respectivos ruidos, luego llama a '__dict__': - freya.haz_ruido() > 'guau' - freya.__dict__ > {'nombre': 'Freya', 'edad': 7} - senna.haz_ruido() > 'miau' - senna.__dict__ > {'nombre': 'Senna', 'edad': 1, 'usa_arenero': True} --- # <span style="color:OrangeRed">Tarea</span> Creen sus propias clases con métodos y atributos. Apliquen herencia, overriding y polimorfismo. Explica para qué lo usarías