herencia

[5]. HERENCIA, QUE ES EN POO.

 

 

Es una propiedad que permite que los objetos sean creados a partir de otros ya existentes, obteniendo características (métodos y atributos) similares a los ya existentes. Es la relación entre una clase general y otra clase mas especifica. Es un mecanismo que nos permite crear clases derivadas a partir de clase base, Nos permite compartir automáticamente métodos y datos entre clases subclases y objetos.

 

La herencia es uno de los mecanismos de la programación orientada a objetos, por medio del cual una clase se deriva de otra, llamada entonces superclase, de manera que extiende su funcionalidad. Una de sus funciones más importantes es la de proveer

Tipos        

Herencia múltiple hace referencia a una característica de los lenguajes de programación orientada a objetos en la que una clase puede heredar comportamientos y características de más de una superclase. Esto contrasta con la herencia simple, donde una clase sólo puede heredar de una superclase

 

Ejemplo

 

Decimos que una gallina es un ave; esto quiere decir que las gallinas tienen características comunes con otras aves (pico, plumas, etc.), es decir que la gallina hereda las características comunes de todas las aves. Pero además, resulta que un ave es un animal, lo que significa que también comparte características comunes al caballo, el perro, el hombre (seeee, como animales) y cualquier otra cosa que pueda ser clasificada como animal..[4]

 

 

Herencia

La herencia se utiliza con frecuencia como un mecanismo para implementar el polimorfismo. En muchos lenguajes orientados a objetos la herencia es la única forma de implementar el polimorfismo. Este mecanismo funciona así:

Una clase puede heredar tanto los atributos como las operaciones de una clase madre, también llamada super clase. Esto implica que una nueva clase que sea bastante similar a otra clase en varios aspectos no necesita re implementar nuevamente todos los métodos de esa segunda clase, sino que puede heredar de ella los métodos y sobre escribir aquellos que son diferentes (como en el caso del ejemplo anterior con las figuras del círculo y el cuadrado).

Nuevamente un ejemplo ilustrará mejor tanta teoría. Usaremos una jerarquía de clases de cuentas bancarias donde podremos depositar en efectivo, obtener el saldo y retirar dinero. Algunas cuentas nos darán interés (el cual, para nuestros propósitos, se calculará sobre cada depósito – una innovación interesante para el mundo financiero!) y otras nos cobrarán una tarifa por realizar extracciones de fondos.

La clase Cuenta Bancaria

Veamos cómo funcionará esto. Primero vamos a considerar los atributos y las operaciones típicas de una cuenta bancaria en un nivel abstracto.

En general es mejor considerar primero las operaciones que se pueden hacer y luego agregar los atributos necesarios para poder llevar a cabo estas operaciones. Entonces, en una cuenta bancaria podemos

·  Depositar efectivo,

·  Retirar efectivo,

·  Revisar nuestro saldo y

·  Transferir fondos a otra cuenta.

Para llevar adelante estas operaciones necesitaremos un número de cuenta bancaria (para las transferencias) y el saldo actual.

Podemos crear una clase que realice esto.

SaldoError = "Lo siento, sólo tiene $%6.2f en su cuenta"
 
class CuentaBancaria:
    def __init__(self, montoInicial):
       self.saldo = montoInicial
       print "Cuenta creada con un saldo de %5.2f" % self.saldo
 
    def deposito(self, monto):
       self.saldo = self.saldo + monto
 
    def extraccion(self, monto):
       if self.saldo >= monto:
          self.saldo = self.salto - monto
       else:
          raise SaldoError % self.saldo
 
    def checkSaldo(self):
       return self.saldo
       
    def transferencia(self, monto, cuenta):
       try: 
          self.extraccion(monto)
          cuenta.deposito(monto)
       except SaldoError:
          print SaldoError

Nota 1: Revisamos el saldo antes de extraer el dinero y el uso de excepciones para manejar los errores. Obviamente no existe un tipo de error SaldoError así que lo creamos nosotros: es simplemente una variable de cadena!

Nota 2: El método transferencia utiliza los métodos extraccion / deposito de la clase CuentaBancaria para realizar su cometido. Esta técnica es muy común en la programación orientada a objetos y se denomina autollamada. Esto implica que las clases derivadas pueden implementar sus propias versiones de los métodos deposito/extraccion pero el método transferencia permanecerá igual para todos los tipos de cuentas bancarias.

Nota 3: Utilizamos el especificador de formato %6.2f para la cadena SaldoError. Este define un formato de seis caracteres con dos dígitos después de la coma.

La clase Cuenta Interés

Ahora utilizaremos la herencia para crear una cuenta que sume el 3% de interés en cada depósito. Será idéntica a nuestra clase estándar CuentaBancaria a excepción del método “deposito”. Simplemente lo “sobreescribimos”:

class CuentaInteres(CuentaBancaria):
   def deposito(self, monto):
       CuentaBancaria.deposito(self, monto)
       self.saldo = self.saldo * 1.03
       

Y eso es todo. Ahora empezamos a comprender el poder de la programación orientada a objetos: todos los demás métodos fueron heredados de la clase CuentaBancaria (al haber puesto CuentaBancaria entre paréntesis luego del nombre de la nueva clase). Notá también que el nuevo método deposito llama al método deposito de la superclase en vez de copiar nuevamente todo el código. Esto tiene a su vez otra ventaja: si el día de mañana modificamos el método deposito de la clase CuentaBancaria (agregándole otras funcionalidades por ejemplo), la subclase recibirá estos cambios automáticamente sin necesidad de reescribir el código.

La clase CuentaRecargo

Esta cuenta es idéntica a nuestra clase CuentaBancaria, salvo que agrega un recargo de $3 por cada extracción de fondos. De la misma manera que con la clase CuentaInteres creamos una clase que heredará los métodos de CuentaBancaria y escribimos un nuevo método extracción.

class CuentaRecargo(CuentaBancaria):
    def __init__(self, montoInicial):
        CuentaBancaria.__init__(self, montoInicial)
        self.recargo = 3
        
    def extraccion(self, monto):
        CuentaBancaria.extracción(self, monto+self.recargo)

Nota 1: Guardamos el recargo como una variable de instancia para poder modificarla si es necesario más adelante. Notá también que podemos llamar al método __init__ heredado de la misma manera que a cualquier otro método.

Nota 2: Simplemente agregamos el recargo al monto de extracción deseado y llamamos al método extraccion de la clase CuentaBancaria para que efectúe la operación.

Nota 3: Aquí introducimos un efecto de rebote: el recargo se aplicará automáticamente tanto en las extracciones como en las transferencias, pero quizás esa era nuestra intención, así que no hay mayores problemas.

Probando nuestro sistema

Para comprobar que nuestro sistema funciona, probá ejecutar el siguiente código en la línea de comando de Python o creando un archivo separado.

from cuentabancaria import *
 
# Primero una cuenta bancaria estándar
a = CuentaBancaria(500)
b = CuentaBancaria(200)
a.extraccion(100)
# a.extraccion(1000)
a.transferencia(100,b)
print "A = ", a.checkSaldo()
print "B = ", b.checkSaldo()
 
 
# Ahora una cuenta con interés
c = CuentaInteres(1000)
c.deposito(100)
print "C = ", c.checkSaldo()
 
 
# Luego una cuenta con recargo
d = CuentaRecargo(300)
d.deposito(200)
print "D = ", d.checkSaldo()
d.extraccion(50)
print "D = ", d.checkSaldo()
d.transferencia(100,a)
print "A = ", a.checkSaldo()
print "D = ", d.checkSaldo()
 
 
# Finalmente transferimos desde una cuenta con recargo a una con interés
# La del recargo deberá cobrarnos el recargo y la cuenta de interés
# deberá acreditarnos el interés
print "C = ", c.checkSaldo()
print "D = ", d.checkSaldo()
d.transferencia(20,c)
print "C = ", c.checkSaldo()
print "D = ", d.checkSaldo()

Ahora sacále el comentario a la línea a.extraccion(1000) para ver si la excepción funciona bien.

Bueno, esto ha sido todo. Un ejemplo razonable y bien directo del funcionamiento de la herencia y cómo esta puede ser utilizada para ampliar un esquema básico con nuevas y poderosas funciones.

Hemos visto cómo podemos construir nuestro programa en diferente pasos y cómo crear un programa para comprobar su funcionamiento. Nuestras rutinas de comprobación no están completas ya que no hemos cubierto cada uno de los posibles casos y todavía quedan varias comprobaciones para hacer, tales como qué sucede si creamos una cuenta con un monto negativo, etc.

Espero que este ejemplo te haya dado una idea de la programación orientada a objetos y te despierte el interés por conocer más acerca de ella por medio de los tutoriales o los libros que te he recomendado. Usaremos nuevamente la programación orientada a objetos en las restantes secciones y específicamente en el “Caso de Estudio”.

 

 

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s


Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

%d personas les gusta esto: