sábado, 2 de diciembre de 2017

Programación orientada a objetos: conceptos teóricos

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.




Programación orientada a objetos: conceptos teóricos



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.

herencia de clases en programación


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.

Interfaces en programación orientada a objetos

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.

simulación herencia múltiple con interfaces

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.

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