Clases
Una clase es un molde que permite definir las características que tomara cada objeto de la clase. Consideremos la clase “coche” como molde de la que luego cada objeto adquiere las características de un coche concreto, por ejemplo micoche. Un coche tiene una serie de atributos que lo convierten en un coche. Cuatro ruedas, un motor, volante, etcétera. También tiene una serie de atributos como el color, el modelo, la marca, etc. Y luego unas funciones como acelerar, frenar, girar.
En programación orientada a objetos tendríamos sólo la clase coche, y luego cada instancia de la clase (cada objeto) es un coche concreto. Un coche azul modelo A es una instancia concreta de la clase coche.
Una clase tiene variables y métodos. Las variables son las que definen los atributos del objeto en concreto, por ejemplo la variable color es la que define si luego una instancia concreta de coche será de color azul verde o rojo. Y los métodos son los que definen las funciones de la clase. En este caso tendríamos los métodos frenar, acelerar y girar.
Así pues la clase coche tendría las variables: color, cilindrada, marca y modelo. Y los métodos Frenear, acelerar y girar. La clase serían los planos y el código cliente la fábrica de coches de la que van saliendo las instancias (coches).
Si lo implementamos como una clase real de software convendría que el código de cliente. El que crea las instancias no tuviera acceso directo a las variables de la clase, el color, la marca etc. Para ello se crean las propiedades que son similares a los métodos pero permiten leer y escribir las variables de la clase de una forma controlada por la propia clase y no por el código cliente. De este modo el código de la clase queda fuera de la vista del código cliente (encapsulación) esto permite que a medida que se crean las clases, estas se pueden almacenar en una librería y el programador se centra sólo en el código cliente que utiliza la clase. Una vez probada la clase no hay que volver a tocarla salvo haya que hacer alguna modificación de su funcionalidad. Esto mantiene controlados los cambios, sabemos que si tocamos las facturas no dejarán de funcionar otras partes del programa y podremos centrarnos sólo en probar de nuevo las facturas.
Este es el concepto de encapsulación. Los tres pilares de la programación orientada a objetos son: la encapsulación que acabamos de explicar la herencia y el polimorfismo que explicamos a continuación.
Herencia y polimorfismo
La herencia consiste en tal y como su palabra indica, crear clases derivadas de una clase padre o base. Así por ejemplo de la clase genérica coche podemos heredar las clases coche deportivo o coche todoterreno. Cada una de estas clases tomaría de la clase base los atributos comunes (color, marca, modelo, acelerar, frenar, etc.) y solamente tendría que implementar los atributos específicos con el consiguiente ahorro de código. Así pues la clase todoterreno podría incluir una variable conteniendo el número de marchas cortas o reductoras (atributo específico de los todoterrenos pero no de los coches en general) e implementar un método llamado meter marcha corta.
En una clase base coche más completa podríamos haber implementado tenía un método llamado MeterMarcha( int numero_de_marchas) y le pasábamos por parámetro la variable de tipo entero numero_de_marchas de este modo el código cliente podría llamar al método MeterMarcha(3) con lo que el coche metería la tercera.
Polimorfismo
Ahora al definir la clase Todoterreno podríamos implementar un método también llamado MeterMarcha( int numero_de_marchas, int marchas_reductoras) en este caso el nombre del método es el mismo que en la clase base pero tiene dos argumentos de entrada en lugar de uno como en la clase base. Esto se llama polimorfismo y permite redefinir el método MeterMarcha para una instancia específica de un todoterreno. De este modo el código cliente puede crear un objeto coche y meter la segunda marcha o crear un objeto todoterreno y meter las tercera reductora pero no tendría sentido meter una marcha reductora a un turismo.
Clases abstractas
Una clase abstracta es una clase padre o base desde la que se está “obligado” a heredar clases hijas, pues no implementará código utilizable. El propio entorno .NET proporciona varias clases base para ser utilizadas por los desarrolladores y derivar clases hija a partir de ellas.
Una clase abstracta determina los miembros que la clase derivada debe implementar. Las clases abstracta se utilizan en casos en los que los diferentes objetos (instancias de la clase) son muy diferentes entre sí aunque pertenecen a una misma clase, por ejemplo un crucero y una piragua son barcos, un jefe de almacén y un operario de fresadora son empleados.
La clase abstracta se crea para evitar la tentación de crear funcionalidad para la clase base, pues en este caso no tendría sentido al ser tan diferentes las instancias. Aunque es posible definir la clase base entera, obliga a implementar los métodos específicos en las clases derivadas. Se pueden declarar referencias a la clase abstracta, pero no se pueden crear instancias de ellas.
Pueden ser abstractas las clases, métodos, propiedades, indizadores y eventos. En general, las clases base no deben contener código que depende de las clases derivadas. Como guía, cada vez que necesitemos una clase genérica ya sea CBarco_generico, CEmpleado_Generico, etc. Deberemos de ponernos en “aviso” de que necesitamos una clase abstracta.
Las clases abstractas deben ser derivadas siempre, pero se permite definir en ella variables y métodos. También es posible declarar los métodos de la clase como abstractos, lo que nos obligará a declararlos en las clases hijas.
Las clases selladas impiden la herencia. También pueden impedir que los miembros de la base se comporten polimórficamente. Algunas veces no se debe permitir a los programadores usar una clase como clase base.
Ocultación de los miembros de la clase base
Aunque un método en la clase derivada tenga el mismo nombre que un método virtual en la clase base, el método de la clase derivada no está destinado a ser el reemplazo del de la clase base del método virtual de la clase. El efecto es que una referencia a la clase base, llama al método base y una referencia a la clase derivada llama al método derivado.
Interfaces
Una interfaz es un contrato donde se especifican
todos los términos y especificaciones (funciones: métodos, propiedades,
eventos, e indizadores) que se deben cumplir
para realizar y concretar el contrato. Una interfaz define funciones
abstractas, esto quiere decir que no poseen implementación.
Una
clase abstracta posee miembros concretos (con implementación) y miembros
abstractos (sin implementación). Las interfaces sólo contienen funciones (miembros) abstractos. Todos los miembros
de una interfaz son implícitamente abstractos. En
una clase se puede implementar n cantidad de interfaces.
Las
interfaces sirven para disolver la ambigüedad producida
por la herencia múltiple de clases. (La herencia múltiple no está permitida en
C#.)
El problema del diamante, es una de las razones que justifica la omisión
de la herencia múltiple en la mayoría de los lenguajes de
programación modernos.
Para evitar este problema, es necesario practicar la herencia simple. Pero las interfaces a través de sus contratos
pueden crear el efecto de herencia múltiple.
Diferencia
entre clases abstractas e interfaces
La interfaz marca unas pautas de funcionamiento pero no nos
da pistas de como lo hace, en cambio la clase abstracta nos define futuros
objetos que tienen pequeñas diferencias a la hora de implementar un pequeño
método
Las interfaces se utilizan principalmente para separar la
interfaz de la implementación en una manera más estricta de como lo hace las
clases abstractas. Una interfaz no permite del todo algún nivel de
implementación en los métodos. Con la clase abstracta si podemos heredar la
implementación de una clase a otra.
En
resumen:
Clase Abstracta
Interface
Contiene tanto métodos ejecutables como métodos
abstractos.
No tiene código de implementación.
Todos sus métodos son abstractos.
Una clase solo puede extender de una única
clase abstracta.
Una clase puede implementar n número de interfaces.
Puede tener variables de instancia, constructores y
cualquiera de los tipos de visibilidad: public, private, protected.
No puede tener variables de instancia o
constructores y solo puede tener métodos públicos.
Clase Abstracta
Interface
Contiene tanto métodos ejecutables como métodos
abstractos.
abstractos.
No tiene código de implementación.
Todos sus métodos son abstractos.
Todos sus métodos son abstractos.
Una clase solo puede extender de una única
clase abstracta.
Una clase puede implementar n número de interfaces.
Puede tener variables de instancia, constructores y
cualquiera de los tipos de visibilidad: public, private, protected.
No puede tener variables de instancia o
constructores y solo puede tener métodos públicos.
Programación orientada a objetos en C#
Definición de una clase
public class Nombre_Clase
{
}
Definición de una propiedad
public string propiedad_titulo
{
get
{
return m_titulo;
}
set
{
m_titulo = value;
}
}
Definición
de un método
public bool MiMetodo(byte argumento)
{
}
Definición de una clase
heredada
class ClaseHija:ClasePadre
{
}
Definición de métodos para
ser sobre-escritos (heredados). Se añade la palabra virtual en la declaración
de cada método (en la clase base) para permitir que las clases derivadas puedan
modificar la implementación de estos métodos.
En clase base o padre:
public virtual void MetodoSobreEscrito()
{
}
Definición de un método
sobreescrito en la clase derivada (polimorfismo), se indica que es
sobre-escrito con la palabra override.
En clase derivada o
hija:
public override void MetodoSobreEscrito()
{
}
Definición de una variable
de la clase base o padre, visible para las clases hijas pero no para el código
cliente. Protected.
protected bool pausado=false;
Static
Si queremos listar todas las marcas de coches no
tendría mucho sentido instanciar un objeto de
la clase coche, para solamente ver las marcas disponibles.
class Coche
{
public static string Marcas()
{
return “Mercedes”;
}
// Aquí irían más miembros de la clase
}
class MarcasApp
{
static void Main()
{
Console.WriteLine("La
marca del coche es: {0}",
Coche.Marca());
string a=Console.ReadLine();
}
}
}
Para hacer que un método
sea static hay que poner esta palabra después del modificador de acceso (si lo
hay) y antes del tipo de retorno del método. Este método devuelve una marca de
un coche. No se ha instanciado ningún objeto de la clase Coche, sino que se ha
puesto directamente el nombre de la clase.
El método main aunque se
declara dentro de una clase, representa el código cliente por lo que siempre va
como static pues no hace referencia a ningún objeto ni se podrá instanciar.
static void Main()
Default
Si definimos una propiedad como default dentro de una clase, será la
primera que se ejecute al crear el objeto. Esto puede ser útil para
validaciones o verificaciones.
Default Public ReadOnly Property ExistePieza (ByVal title As String) As CPieza
Clases abstractas
Definición de una clase
abtracta
public abstract class Nombre_Clase
{
}
Definición de un método abstracto
public abstract string metodo_abstracto
{
}
Definición de
un método derivado de una clase abstracta. Para declarar un método o una propiedad abstracta heredada se puede
reemplazar en una clase derivada pero hay que poner el modificador override.
abstract class Clase_Abstracta
{
abstract public int Metodo();
}
class Clase_Hija : Clase_Abstracta
{
public override int Metodo()
{
}
Para
evitar que una clase se convierta en clase base
sealed class Nombre_Clase
{
}
Definición de un método que
no pueda comportarse polimórficamente
new public void metodo_base
{
}
No
se puede modificar una clase abstracta con el modificador sellado porque los dos modificadores tienen significados
opuestos. El modificador
sealed
evita
la herencia de una clase y el modificador abstract
requiere
la herencia de una clase.
Utilizar
los modificadores static o virtual en una declaración de
método abstracto produce un error.
No es correcto utilizar el modificador
abstract
para
una propiedad estática.Interfaces
Declarar una interfaz
interface IContenedor
{
}
{
}
Declarar una clase que
implementa una interfaz es como declarar una clase derivada, en este caso en vez de derivar de una clase base lo hace de una interfaz.
class Contenedor : IContenedor
{
}
{
}
No hay comentarios:
Publicar un comentario