IMPLEMENTACIÓN DE HERENCIA EN OBJETOS
* Herencia MultipleHerencia Simple La herencia en C++ es un mecanismo de abstracción creado para poder facilitar, y mejorar el diseño de las clases de un programa. Con ella se pueden crear nuevas clases a partir de clases ya hechas, siempre y cuando tengan un tipo de relación especial. En la herencia, las clases derivadas “heredan” los datos y las funciones miembro de las clases base, pudiendo las clases derivadas redefinir estos comportamientos (polimorfismo) y añadir comportamientos nuevos propios de las clases derivadas. Para no romper el principio de encapsulamiento (ocultar datos cuyo conocimiento no es necesario para el uso de las clases), se proporciona un nuevo modo de visibilidad de los datos/funciones: “protected”. Cualquier cosa que tenga visibilidad protected se comportará como pública en la clase Base y en las que componen la jerarquía de herencia, y como privada en las clases que NO sean de la jerarquía de la herencia. Antes de utilizar la herencia, nos tenemos que hacer una pregunta, y si tiene sentido, podemos intentar usar esta jerarquía: Si la frase <claseB> ES-UN <claseA> tiene sentido, entonces estamos ante un posible caso de herencia donde clase A será la clase base y clase B la derivada. Ejemplo: clases Barco, Acorazado, Carguero, etc… un Acorazado ES-UN Barco, un Carguero ES-UN Barco, un Trasatlántico ES-UN Barco, etc.
En este ejemplo tendríamos las cosas generales de un Barco (en C++) class Barco {
protected:
char* nombre;
float peso;
public:
//Constructores y demás funciones básicas de barco
}; y ahora las características de las clases derivadas, podrían (a la vez que heredan las de barco) añadir cosas propias del subtipo de barco que vamos a crear, por ejemplo: Class Carguero: public Barco { // Esta es la manera de especificar que hereda de Barco
private:
float carga;
//El resto de cosas
};
Class Acorazado: public Barco {
private:
int numeroArmas;
int Soldados;
// Elresto de cosas
}; Por último, hay que mencionar que existen 3 clases de herencia que se diferencian en el modo de manejar la visibilidad de los componentes de la clase resultante: • Herencia publica (class Derivada: public Base ) : Con este tipo de herencia se respetan los comportamientos originales de las visibilidades de la clase Base en la clase Derivada. • Herencia privada (clase Derivada: private Base) : Con este tipo de herencia todo componente de la clase Base, será privado en la clase Derivada (ojo! siempre será privado aunque ese dato fuese público en la clase Base) • Herencia protegida (clase Derivada: protected Base) : Con este tipo de herencia, todo componente publico y protegido de la clase Base, será protegido en la clase Derivada, y los componentes privados, siguen siendo privados. Herencia Múltiple La herencia múltiple es el mecanismo que permite al programador hacer clases derivadas a partir, no de una sola clase base, sino de varias. Para entender esto mejor, pongamos un ejemplo: Cuando ves a quien te atiende en una tienda, como persona que es, podrás suponer que puede hablar, comer, andar, pero, por otro lado, como empleado que es, también podrás suponer que tiene un jefe, que puede cobrarte dinero por la compra, que puede devolverte el cambio, etc.
Si esto lo trasladamos a la programación sería herencia múltiple (clase empleado_tienda): class Persona {
…
Hablar();
Caminar();
…
};
class Empleado {
Persona jefe;
int sueldo;
Cobrar();
…
};
class empleado_tienda: public Persona, Empleado {
…
Almacenar Stock();
Comprobar Existencias?();
…
}; Por tanto, es posible utilizar más de una clase para que otra herede sus características.
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.
Lenguajes que soportan herencia múltiple en su mayor parte son: C++, Centura SQL Windows, CLOS, Eiffel, Object REXX, Perl y Python.
La herencia múltiple permite a una clase tomar funcionalidades de otras clases, como permitir a una clase llamada MusicoEstudiante heredar de una clase llamada Persona, una clase llamada Músico, y una clase llamada Trabajador. Esto puede ser abreviado como MusicoEstudiante : Persona, Músico, Trabajador.
Ambigüedades
En la herencia múltiple aparecen ambigüedades, como en el ejemplo de encima: si la clase Músico heredaba de Persona y Trabajador, y la clase Trabajador heredaba de Persona. Existirían las siguientes reglas:
• MusicoEstudiante : Persona, Músico, Trabajador
• Músico : Persona, Trabajador
• Trabajador: Persona
Si un compilador está mirando la clase MusicoEstudiante necesita saber si debe juntar las características iguales o si deben estar separadas. Por ejemplo, tendría sentido unir las características "Edad" de Persona para MusicoEstudiante. La edad de una persona no cambia si le consideras una Persona, un Trabajador o un Músico. Sin embargo, tendría sentido separar la característica "Nombre" de Persona y Músico si los músicos usan un nombre artístico diferente de su nombre real. Las opciones de juntar y separar son válidas según el contexto, y sólo el programador sabe qué opción es correcta para la clase que está diseñando.
Cada lenguaje de programación trata estos problemas de herencia repetida de diferente forma:
• C++ requiere que el programador establezca de qué clase padre vendrá la característica a usar. Por ejemplo con "Trabajador::Persona.Edad". C++ no soporta herencia repetida explícita porque no habría forma de indicar qué superclase usar.
• CLOS permite al programador control total del método de combinación, y si no es suficiente, el protocolo de metaobjetos ofrece al programador formas de modificar la herencia, envío de métodos, instanciación de clases, y otros mecanismos internos sin afectar a la estabilidad del sistema.
• Eiffel permite al programador explicitar si junta o separa características que son heredadas de superclases. Eiffel juntará características automáticamente si tienen el mismo nombre e implementación. El programador tiene la opción de renombrar las características para separarlas. Eiffel también permite explicitar herencia repetida como A: B, B.
• Logtalk soporta tanto interfaces como multi-herencia de implementación, permitiendo declarar alias de métodos que ofrecen renombrar y acceder a métodos que quedarían ocultados por el mecanismo de resolución de conflictos convencional.
• Perl usa la lista de clases para heredar de una lista ordenada. El compilador usa el primer método que encuentra mediante búsqueda en profundidad por la lista de superclases.
Java, Nemerle, Delphi, C# y Objective-C no permiten herencia múltiple; esto hace que no haya ambigüedad. Sin embargo, permiten a las clases implementar múltiples interfaces.
Debate
Hay debate sobre si la herencia múltiple puede ser implementada de forma simple y sin ambigüedad. Con frecuencia es criticada por su aumentada complejidad y su ambigüedad, así como los problemas de versiones y mantenimiento que puede causar (a menudo resumido como el problema del diamante).
No hay comentarios:
Publicar un comentario