Lenguaje C# Parte 5 Herencia, Clases Abstractas, Polimorfismo
Herencia de Clases
La herencia se realiza a través de una derivación, lo que significa que una clase se declara utilizando una
clase base de la cual hereda los datos y el comportamiento. Las clases pueden heredar de otra clase. Para
conseguir esto, se coloca un signo de dos puntos después del nombre de la clase al declarar la clase y se denomina la clase de la cual se hereda (la clase base) después del signo de dos puntos.
En el ejemplo anterior, la clase B es claramente B y A. Cuando se tiene acceso a un objeto B, se puede utilizar la operación de conversión de tipos para convertirlo en un objeto A (casting o conversión explícita). La conversión de tipos no cambia el objeto B, pero la vista del objeto B se restringe a los datos y comportamientos de A. Después de convertir un objeto B en un objeto A, es posible volver a convertir ese objeto A en un objeto B. No todas las instancias de A se pueden convertir en B, sólo aquellas que son realmente instancias de B. Si se tiene acceso a la clase B como tipo B, se obtienen los datos y comportamientos tanto de la clase A como de la clase B.
Nota: Las estructuras no pueden heredar de otras estructuras o clases.
Clases y miembros de clase abstractos y sellados
La palabra clave abstract permite crear clases y miembros de clase únicamente con propósitos de herencia: para definir características de clases derivadas, no abstractas. La palabra clave sealed permite impedir la
herencia de una clase o de ciertos miembros de clase marcados previamente como virtuales.
Clases y miembros de clase abstractos
No se pueden crear instancias de una clase abstracta. El propósito de una clase abstracta es proporcionar una definición común de una clase base que múltiples clases derivadas pueden compartir. Por ejemplo, una biblioteca de clase puede definir una clase abstracta que se utiliza como parámetro para muchas de sus funciones y solicitar a los programadores que utilizan esa biblioteca que proporcionen su propia implementación de la clase mediante la creación de una clase derivada.
Las clases abstractas también pueden definir métodos abstractos. Esto se consigue agregando la palabra
clave abstract antes del tipo de valor que devuelve el método.
Los métodos abstractos no tienen ninguna implementación, de modo que la definición de método va
seguida por un punto y coma en lugar de un bloque de método normal. Las clases derivadas de la clase
abstracta deben implementar todos los métodos abstractos. Cuando una clase abstracta hereda un método virtual de una clase base, la clase abstracta puede reemplazar el método virtual con un método abstracto.
Si un método virtual se declara abstracto, sigue siendo virtual para cualquier clase que se herede de la clase abstracta. Una clase que hereda un método abstracto no puede tener acceso a la implementación original del método; en el ejemplo anterior, Algo() de la clase F no puede llamar a Algo() de la clase D. De esta forma, una clase abstracta puede obligar a las clases derivadas a proporcionar nuevas implementaciones de método para los métodos virtuales.
Clases y miembros de clase sellados
Las clases pueden declararse como selladas. Esto se logra colocando la palabra clave sealed antes de la
palabra clave class en la definición de clase.
Un miembro de clase, método, campo, propiedad o evento de una clase derivada que reemplaza a un
miembro virtual de la clase base puede declarar ese miembro como sellado. Esto niega el aspecto virtual del miembro para cualquier clase derivada adicional. Esto se logra colocando la palabra clave sealed antes de la palabra clave override en la declaración del miembro de clase.
Polimorfismo
A través de la herencia, una clase puede utilizarse como más de un tipo; puede utilizarse como su propiotipo, cualquier tipo base o cualquier tipo de interfaz si implementa interfaces. Esto se denomina
polimorfismo. En C#, todos los tipos son polimórficos. Los tipos se pueden utilizar como su propio tipo o
como una instancia de Object, porque cualquier tipo trata automáticamente a Object como tipo base.
El polimorfismo no sólo es importante para las clases derivadas, sino también para las clases base.
Cualquiera que utilice la clase base podría, de hecho, estar utilizando un objeto de la clase derivada que se haya convertido en el tipo de clase base. Los diseñadores de una clase base pueden anticipar qué aspectos de su clase base cambiarán probablemente para un tipo derivado. Por ejemplo, es posible que una clase base para automóviles contenga un comportamiento sujeto a cambios si el automóvil en cuestión es un vehículo familiar o uno descapotable. Una clase base puede marcar esos miembros de clase como virtuales, lo cual permite que las clases derivadas que representan automóviles descapotables y vehículos familiares reemplacen ese comportamiento.
Cuando una clase derivada hereda de una clase base, obtiene todos los métodos, campos, propiedades y eventos de la clase base. Para cambiar los datos y el comportamiento de una clase base, existen dos opciones: se puede reemplazar el miembro base por un nuevo miembro derivado o se puede reemplazar un miembro base virtual.
Para reemplazar un miembro de una clase base por un nuevo miembro derivado, se requiere la palabra clave new. Si una clase base define un método, campo o propiedad, la palabra clave new se utiliza para crear una nueva definición de ese método, campo o propiedad en una clase derivada. La palabra clave new se coloca antes del tipo de valor devuelto de un miembro de clase que se reemplaza.
Cuando se utiliza la palabra clave new, se llama a los nuevos miembros de clase en lugar de los miembros de
clase base que se han reemplazado. Esos miembros de clase base se denominan miembros ocultos. Aún es
posible llamar a los miembros de clase ocultos si una instancia de la clase derivada se convierte en una
instancia de la clase base.
Para que una instancia de una clase derivada controle por completo un miembro de clase de una clase base, la clase base debe declarar ese miembro como virtual. Esto se consigue agregando la palabra clave virtual antes del tipo de valor devuelto del miembro. Una clase derivada tiene entonces la opción de utilizar la palabra clave override, en lugar de new, para reemplazar la implementación de la clase base por la propia.
Los métodos y propiedades virtuales permiten hacer planes para una expansión futura. El hecho de llamar a un miembro virtual sin importar cuál es el tipo que el llamador utiliza proporciona a las clases derivadas la opción de cambiar completamente el comportamiento aparente de la clase base.
Los miembros virtuales siguen siendo virtuales de forma indefinida, independientemente de cuántas clases se hayan declarado en la clase que originalmente declaró el miembro virtual. Si la clase A declara un miembro virtual, la clase B deriva de A y la clase C deriva de B, la clase C hereda el miembro virtual y tiene la opción de reemplazarlo, independientemente de si la clase B declaró la sustitución de ese miembro.