{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "view-in-github", "colab_type": "text" }, "source": [ "\"Open" ] }, { "cell_type": "markdown", "metadata": { "id": "jdZC0sFpakhp" }, "source": [ "# Herencia [1]\n", "En Programación Orientada a Objetos la Herencia es el mecanismo que permite crear nuevas clases a partir de las preexistentes. \n", "La herencia nos permite crear otras clases sin tener que empezar de cero. Utilizamos una clase padre con las características de base y le agregamos las características particulares a la clase hija." ] }, { "cell_type": "markdown", "metadata": { "id": "JXO9e480akh1" }, "source": [ "La ventaja de la herencia es la reutilización de código. \n", "La herencia nos permite modelar otros sistemas sin tener que empezar de cero, utilizamos una clase *Padre* con las características de base y le agregamos las características particulares a la clase *Hija*. \n", "\n", "![herencia](https://github.com/financieras/pyCourse/blob/main/jupyter/img/herencia.png?raw=1)" ] }, { "cell_type": "markdown", "metadata": { "id": "7k9H9-Iyakh6" }, "source": [ "Cuando una clase hereda de otra, hereda todos sus métodos y atributos. \n", "* clase principal, clase padre o superclase\n", "* clase hija o subclase\n", "\n", "La clase hija hereda los métodos y atributos de la clase padre pero además puede definir sus propios métodos y atributos.\n", "\n", "**Ejemplo 1** \n", "La clase Figura es la clase padre que tiene tres clases hijas: Rectangulo, Circulo, Hexagono.\n", "\n", "**Ejemplo 2** \n", "La clase Pet es la clase padre que tiene dos clases hijas: Dog, Cat.\n", "\n", "**Ejemplo 3** \n", "La clase Vehiculo es la clase padre que tiene varias clases hijas: Moto, Coche, Furgoneta, Camion, Bici." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "id": "YOxMBn0oakiG", "outputId": "868ba5f0-acdf-4a29-ddaf-dda02d8abaae", "colab": { "base_uri": "https://localhost:8080/" } }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Marca: Honda \n", "Modelo: Rebel \n", "En marcha: False \n", "Acelerando: False \n", "Frenando: False\n" ] } ], "source": [ "class Vehiculo(): # primero va el constructor con las propiedades\n", " def __init__(self, marca, modelo): # marca y modelo nos permiten dar un estado inicial a los objetos que hereden de Vehiculo\n", " self.marca = marca # la marca que pasemos como parámetro al constructor será nuestra self. marca del objeto\n", " self.modelo = modelo # el modelo que pasemos como parámetro al constructor será nuestro self. modelo\n", " self.enmarcha = False # inicialmente los objetos creados no estarán en marcha\n", " self.acelera = False # inicialmente los objetos creados no estarán acelerando\n", " self.frena = False # inicialmente los objetos creados no estarán frenando\n", "\n", " def arrancar(self): # método. Los métodos nos dan el comportamiento del objeto\n", " self.enmarcha=True\n", "\n", " def acelerar(self): # método. Estos métodos permiten cambiar las propiedades definidas en el constructor\n", " self.acelera = True\n", "\n", " def frenar(self): # método\n", " self.frena = True\n", "\n", " def estado(self):\n", " print(f\"Marca: {self.marca} \\nModelo: {self.modelo} \\\n", " \\nEn marcha: {self.enmarcha} \\nAcelerando: {self.acelera} \\nFrenando: {self.frena}\")\n", "\n", "class Moto(Vehiculo): # Así indicamos que la clase Moto hereda de Vehiculo\n", " pass # No añadimos nada para comprobar que Moto goza de las propiedades y métodos de Vehiculo\n", "\n", "miMoto=Moto(\"Honda\", \"Rebel\") # creamos una instancia que hereda tb el constructor por lo que se han de pasar marca y modelo\n", "miMoto.estado() # al heredar de Vehiculo puedo usar los métodos heredados" ] }, { "cell_type": "markdown", "metadata": { "id": "uhw52xZjakiP" }, "source": [ "## Sobreescritura de métodos\n", "Una clase que hereda de otra adquiere sus métodos y propiedades, pero a su vez puede tener sus propios métodos y propiedades. \n", "Pensemos en el comportamiento que pueda tener una moto que no tengan todos los vehículos, por ejemplo, hacer el caballito. La variable será hcaballito (hacer el caballito)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "id": "niHBMhtlakiQ", "outputId": "46df7a34-29e3-446c-b6d1-d3cb7016ab4a", "colab": { "base_uri": "https://localhost:8080/" } }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Marca: Honda \n", "Modelo: Rebel \n", "En marcha: False \n", "Acelerando: False \n", "Frenando: False\n" ] } ], "source": [ "class Vehiculo():\n", " def __init__(self, marca, modelo):\n", " self.marca = marca\n", " self.modelo = modelo\n", " self.enmarcha = False\n", " self.acelera = False\n", " self.frena = False\n", "\n", " def arrancar(self):\n", " self.enmarcha = True\n", "\n", " def acelerar(self):\n", " self.acelera = True\n", "\n", " def frenar(self):\n", " self.frena = True\n", "\n", " def estado(self):\n", " print(f\"Marca: {self.marca} \\nModelo: {self.modelo} \\\n", " \\nEn marcha: {self.enmarcha} \\nAcelerando: {self.acelera} \\nFrenando: {self.frena}\")\n", "\n", "class Moto(Vehiculo):\n", " hcaballito = \"\" # creamos la nueva variable: haciendo el caballito\n", " def caballito(self): # creamos el método caballito\n", " self.hcaballito=\"Voy haciendo el caballito\" # el método modifica el valor de la variable hcaballito\n", "\n", "miMoto=Moto(\"Honda\", \"Rebel\")\n", "miMoto.caballito() # invocamos el nuevo método\n", "miMoto.estado() # no da error, pero no informa de que estamos haciendo el caballito\n", " # será necesario sobrescribir el método estado" ] }, { "cell_type": "markdown", "metadata": { "id": "0UXr5WUUakic" }, "source": [ "Ahora un objeto de tipo moto puede usar seis métodos que son los cinco heredados (incluyendo el construcctor) y el suyo propio." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "id": "jTjF-Siaakie", "outputId": "b33ee064-ec53-4244-d123-53373e404b18", "colab": { "base_uri": "https://localhost:8080/" } }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Marca: Honda \n", "Modelo: Rebel \n", "En marcha: False \n", "Acelerando: False \n", "Frenando: False \n", "Voy haciendo el caballito\n", "==============================\n", "Marca: VW \n", "Modelo: Golf \n", "En marcha: False \n", "Acelerando: False \n", "Frenando: False\n", "==============================\n", "Marca: Harley-Davidson \n", "Modelo: Fat Boy \n", "En marcha: False \n", "Acelerando: False \n", "Frenando: False \n", "\n" ] } ], "source": [ "class Vehiculo():\n", " def __init__(self, marca, modelo):\n", " self.marca = marca\n", " self.modelo = modelo\n", " self.enmarcha = False\n", " self.acelera = False\n", " self.frena = False\n", " def arrancar(self):\n", " self.enmarcha = True\n", " def acelerar(self):\n", " self.acelera = True\n", " def frenar(self):\n", " self.frena = True\n", " def estado(self):\n", " print(f\"Marca: {self.marca} \\nModelo: {self.modelo} \\\n", " \\nEn marcha: {self.enmarcha} \\nAcelerando: {self.acelera} \\nFrenando: {self.frena}\")\n", "\n", "class Moto(Vehiculo):\n", " hcaballito = \"\"\n", " def caballito(self):\n", " self.hcaballito = \"Voy haciendo el caballito\"\n", "\n", " def estado(self): # = nombre y nº de parámetros que el método sobrescrito de la clase padre\n", " print(f\"Marca: {self.marca} \\nModelo: {self.modelo} \\\n", " \\nEn marcha: {self.enmarcha} \\nAcelerando: {self.acelera} \\nFrenando: {self.frena}\\\n", " \\n{self.hcaballito}\")\n", "\n", "miMoto=Moto(\"Honda\", \"Rebel\")\n", "miMoto.caballito() # invocamos el nuevo método y ahora si vemos que hace el caballito\n", "miMoto.estado() # si no hubiéramos invocado el método caballito no se imprimiría Voy...\n", "\n", "print(\"=\"*30)\n", "miCoche=Vehiculo(\"VW\", \"Golf\") # creamos un vehículo que no sea una moto\n", "miCoche.estado() # al invocar su estado se aplica el estado de la clase Vehiculo\n", "\n", "print(\"=\"*30)\n", "motoClasica=Moto(\"Harley-Davidson\", \"Fat Boy\") # creamos una moto con la que no haremos el caballito\n", "motoClasica.estado() # al invocar su estado se aplica el estado de la clase Moto\n", " # pero previamente no hemos invocado el método caballito()" ] }, { "cell_type": "markdown", "metadata": { "id": "w6ek6PJ4akis" }, "source": [ "Cuando escribimos miMoto.estado() surge una pregunta: ¿Estamos llamando al método estado de la clase Vehiculo o al método estado de la clase Moto? \n", "El método estado de la clase Moto sobrescribe (anula, invalida) el método estado de la clase Vehiculo. \n", "Invocar o no el método caballito es opcional, si no se invoca no se imprime la frase 'Voy haciendo el caballito', simplemente se imprime \"\" que es el valor de la variable hcaballito cuando el método no actúa." ] }, { "cell_type": "markdown", "metadata": { "id": "4WxbTFqAaki4" }, "source": [ "## Jerarquía\n", "Supongamos que creamos la clase Quad que hereda de la clase Moto y esta a su vez hereda de la clase Vehiculo. Esto es lo que se llama una cadena de herencias o jerarquía de herencias. \n", "La clase Quad heredaría el método estado de la clase Moto y no el método estado de la clase Vehiculo ya que Quad hereda directamente de Moto." ] }, { "cell_type": "markdown", "metadata": { "id": "Mnuvhx3jakjA" }, "source": [ "## Clase Furgoneta\n", "Si creamos la clase Furgoneta lo lógico es que herede de la clase Vehiculo y no de la clase Moto. \n", "La clase Furgoneta tendrá un nuevo comportamiento (método) que será la capacidad de cargar (llevar carga)." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "id": "K8KfkrkYakjD", "outputId": "56b9ab52-ddad-49b2-d3e4-dd5264fafc2f", "colab": { "base_uri": "https://localhost:8080/" } }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Marca: Nissan \n", "Modelo: N100 \n", "En marcha: True \n", "Acelerando: False \n", "Frenando: False\n", "La Furgoneta está cargada\n" ] } ], "source": [ "class Vehiculo():\n", " def __init__(self, marca, modelo):\n", " self.marca = marca\n", " self.modelo = modelo\n", " self.enmarcha = False\n", " self.acelera = False\n", " self.frena = False\n", "\n", " def arrancar(self):\n", " self.enmarcha = True\n", "\n", " def acelerar(self):\n", " self.acelera = True\n", "\n", " def frenar(self):\n", " self.frena = True\n", "\n", " def estado(self):\n", " print(f\"Marca: {self.marca} \\nModelo: {self.modelo} \\\n", " \\nEn marcha: {self.enmarcha} \\nAcelerando: {self.acelera} \\nFrenando: {self.frena}\")\n", "\n", "class Furgoneta(Vehiculo): # creamos la clase Furgoneta que hereda de la clase Vehiculo\n", " def cargada(self, carga): # la variable carga será True o False\n", " self.carga = carga\n", " if self.carga:\n", " return \"La Furgoneta está cargada\" # en este método usamos un return para informar\n", " else:\n", " return \"La Furgoneta no está cargada\"\n", "\n", "miFurgoneta=Furgoneta(\"Nissan\",\"N100\")\n", "\n", "miFurgoneta.arrancar()\n", "miFurgoneta.estado()\n", "print(miFurgoneta.cargada(True)) # usamos un print ya que el método 'cargada' se creó con un reuturn\n", "" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" }, "colab": { "name": "calisto2_0210.ipynb", "provenance": [], "include_colab_link": true } }, "nbformat": 4, "nbformat_minor": 0 }