La Programación Orientada a Objetos en Acción: Herencia y Polimorfismo

Herencia y Polimorfismo con C# .NET

Bueno, ya que hemos hablado un poco de los conceptos básicos de la POO pongamoslos en práctica.  Creo que un buen ejemplopara entender lo que es la POO y como se traduce en código es la clasificación del Reino Animal.  Según los expertos y en base a la siguiente tabla que encontré en http://thales.cica.es/rd/Recursos/rd99/ed99-0040-02/clasific.html los seres vivos se clasifican así:

Clasificación Seres Vivos
Clasificación Seres Vivos

El articulo titulado Animalia, el cual encontré en http://es.wikipedia.org/wiki/Animalia menciona que los animales llevan a cabo las siguientes funciones esenciales: alimentación, respiración, circulación, excreción, respuesta, movimiento y reproducción.

En base a esto, vamos a crear nuestra clase base Animal la cual tendrá todas estas acciones comunes a todos los animales. De igual manera, en esta clase escribiremos los atributos comunes a todos los animales para que mediante la herencia sean heredados a todas las subclases . En el caso de que encontramos otra acción (que en código serían otro método a implementar) o característica (atributo) que aplique para todos los animales lo ideal sería agregarla en esta clase para que sea heredada en la jerarquía de clases de nuestra aplicación. Por ejemplo, si quisieramos agregar la acción de Dormir, sólo tendríamos que agregar el método Dormir() en la clase Animal.

Es importante destacar que hemos definido nuestra clase animal como abstract ya que no nos interesa crear instancias u objetos de tipo Animal. Si así fuera el caso, tendríamos que quitar la palabra reservada abstract para poder crear las instancias.

Nuestra clase base Animal quedaría entonces de la siguiente manera:

using System;

namespace ReinoAnimal
{
    /// <summary>
    /// Clase padre para todos las clases del Reino Animal.  Servirá como clase base para todas las clases que correspondan a un Animal. 
    /// Por ende, en esta clase se encontrarán todas los atributos en común en todos los animales.
    /// </summary>
    public abstract class Animal
    {
        /// <summary>
        /// Para nuestro ejemplo, todos los animales tienen una clasificación en específico.
        /// </summary>
        #region [ Propiedades ]
        public string Reino { get; set; }
        public string Filum { get; set; }
        public string Clase { get; set; }
        public string Orden { get; set; }
        public string Familia { get; set; }
        public string Genero { get; set; }
        public string Especie { get; set; }
        #endregion

        #region [ Constructor ]
        /// <summary>
        /// Constructor de la clase base para todos los seres vivos que pertenecen al Reino Animal.
        /// </summary>
        public Animal()
        {
            this.Reino = "Animalia";

            Console.WriteLine("Los animales pertenecen a uno de los 5 reinos de la naturaleza.");
        }
        #endregion

        /// <summary>
        /// Las acciones en común para todos los animales es comer, comunicarse entre ellos, desplazarse, reproducirse y respirar. 
        /// Para nuestro ejemplo, consideraremos estos metodos en común para todos los animales. Si encontramos otro comportamiento en común 
        /// para todos los animales, este sería el lugar indicado para agregarlo y que todas las subclases hereden este comportamiento.
        /// 
        /// Un ejemplo seria el Dormir.
        /// </summary>
        #region [ Metodos Abstractos ]
        public virtual void Alimentacion() { }
        public virtual void Comunicacion() { }
        public virtual void Movimiento() { }
        public virtual void Reproduccion() { }
        public virtual void Respiracion() { }
        #endregion
    }
}

Observa que los métodos los hemos definido como virtual para que podamos implementarlos en las clases que deriven de ésta en manera concreta.  Recuerda que un método definido como virtual permite invalidar un miembro de una clase derivada, lo que quiere decir que lo puedes implementar de manera concreta en la subclase si asi lo requiere. En caso de que no sea necesario, el compilador no te exigira que lo implementes.  Más adelante veremos el por qué nos conviene en este caso utilizar este tipo de modificador en vez del abstract que en cambio requiere que se invalide un miembro de clase en la clase derivada.

Ya que tenemos nuestra clase base implementada, tenemos que crear las clases que heredaran el comportamiento y atributos; es decir las subclases de la clase Animal. Como  podemos ver en la imagen,  los animales se diveden en Vertebrados e Invertebrados.  Para nuestro ejemplo solo implementaremos la clase Vertebrados.  En esta clase, escribiremos todas las propiedades y métodos que caracterizan a todos los vertebrados y que seguramente heredaran todas las clases que deriven de ésta. Cómo ya sabemos, un animal verterbrado pertence o deriva de la clase animal.  Observa que con la instrucción public class Vertebrado : Animal estamos indicando que la clase de tipo Vertebrado esta heredando de la clase Animal.

Nuestra clase Vertebrado queda de la siguiente manera:

using System;

namespace ReinoAnimal
{
    /// <summary>
    /// Subclase perteneciente a la clase padre Animal y la cual hereda los metodos y atributos definidos en esta.
    /// 
    /// Esta clase sería donde tendriamos todas las características de los animales vertebrados.
    /// </summary>
    public class Vertebrado : Animal
    {
        #region [ Propiedades ]
        /// <summary>
        /// Para nuestros ejemplo, lo que hace único a los vertebrados es que cuentan con un esqueleto.
        /// </summary>
        public string Esqueleto { get; set; }
        /// <summary>
        /// Numero de vertebras que conforman su columna vertebral.
        /// </summary>
        public int Vertebras { get; set; }
        /// <summary>
        /// Hay individuos machos e individuos hembras, es decir, el sexo está diferenciado.
        /// </summary>
        public string Sexo { get; set; }

        public tSangre tSangre { get; set; }
        public tRespiracion tRespiracion { get; set; }
        #endregion

        #region [ Constructor ]
        /// <summary>
        /// Constructor de la clase y que a su vez hereda el de su clase padre.
        /// </summary>
        public Vertebrado()
            : base()
        {
            this.Filum = "Chordata";
            Console.WriteLine("Debido a que soy un animal vertebrado poseo un esqueleto y una columna vertebral");
        }
        #endregion
    }
}

Continuando con la clasificación de la imagen, tenemos que los vertebrados se dividen en:

  • Mamíferos
  • Aves
  • Peces
  • Anfibios
  • Reptiles.

Para nuestro ejmplo crearemos  las clases Mamiferos, Aves y Anfibios, las cuales derivaran de la clase Vertebrado y por consiguiente heredarán toda su funcionalidad y atributos.

La clase Mamifero queda de la siguiente manera:

using System;

namespace ReinoAnimal
{
    /// <summary>
    /// Subclase de Vertebrado y que heredara los atributos tanto de Vertebrado como de Animal.
    /// 
    /// En esta clase tendremos las caracteristicas de un mamifero.
    /// </summary>
    public class Mamiferos : Vertebrado
    {
        #region [ Propiedades ]        
        public string Piel { get; set; }
        public int Extremedidades { get; set; }
        #endregion

        #region [ Constructor ]
        public Mamiferos()
            : base()
        {
            this.Clase = "Mammalia";

            Console.WriteLine("Debido a que soy un mamífero mi temperatura corporal es constante, es decir, soy de sangre caliente");
        }
        #endregion

        #region [ Metodos ]
        public override void Respiracion()
        {
            Console.WriteLine("Respiro por medio de mis pulmones");
        }

        public override void Reproduccion()
        {
            Console.WriteLine("La mayoría somos vivíparos");
        }
        #endregion

    }
}

Como puedes ver, aqui definimos la propiedades Piel y Extremidades que son caracteristicas únicas de los mamíferos. De igual manera, implementamos los métodos Respiracion() y Reproduccion() ya que todos los mamíferos lo hacen de la misma manera.  En caso de que existiera una excepción, en la subclase se puede modificar este comportamiento dado que el modificador virtual así nos lo permite hacerlo. Sino no es necesario, simplemente utilizará el método de la clase padre inmediata superior en un orden de abajo hacia arriba. Por ejemplo, si una subclase de Mamifero, invocara el método alimenta, como la clase Mamífero no lo implenta en concreto, la subclase de Mamífero invocara al metodo alimenta pero de la clase Vertebrado. Si la clase Vertebrado lo implementa utilizará, sino buscara el método en la clase inmediata superior.

La clase Anfibios queda de la siguiente manera:

using System;

namespace ReinoAnimal
{
    public class Anfibios:Vertebrado
    {
        #region [ Propiedades ]
        #endregion

        #region [ Constructor ]
        public Anfibios()
        {
            this.Clase = "Amphibia";

            Console.WriteLine("Mi temperatura corporal es variable, es decir, soy de sangre fría.");
        }
        #endregion

        #region [ Metodos ]
        public override void Comunicacion()
        {
            Console.WriteLine("Ribit! Ribbit!");
        }

        public override void Reproduccion()
        {
            Console.WriteLine("Somos ovíparos que nos reproducimos por huevos");
        }

        public override void Respiracion()
        {
            Console.WriteLine("La respiración se realiza por branquias (externas o internas) durante la fase larvaria, pero al llegar a la edad adulta aquéllas suelen sustituirse por unos pulmones muy rudimentarios, ya que la mayor parte del proceso respiratorio se efectúa a través de la piel");
        }
        #endregion
    }
}

Y finalmente la clase Aves queda implementada de la siguiente manera:

using System;

namespace ReinoAnimal
{
    /// <summary>
    /// Subclase de Vertebrado y que heredara los atributos tanto de Vertebrado como de Animal.
    /// 
    /// En esta clase tendremos las caracteristicas de las aves.
    /// </summary>
    public class Aves : Vertebrado
    {
        #region [ Propiedades ]
        public string Pico { get; set; }
        public string Alas { get; set; }
        #endregion

        #region [ Constructor ]
        /// <summary>
        /// Constructor para los objetos de tipo Aves
        /// </summary>
        public Aves()
            : base()
        {
            this.Clase = "Aves";

            Console.WriteLine("Debido a que soy un ave tengo mi cuerpo cubierto de plumas");
        }
        #endregion

        #region [ Metodos  ]
        public override void Alimentacion()
        {
            Console.WriteLine("Dependiendo de la especie, somos carnivoras, hervívoras, insectívoras u omnívoras");
        }
        public override void Comunicacion()
        {
            Console.WriteLine("El sonido que emitimos las aves es demonimado Trinar.");
        }
        public override void Movimiento()
        {
            Console.WriteLine("Me desplazo sobre la tierra con mis 2 patas y también puedo volar con mis alas");
        }
        public override void Reproduccion()
        {
            Console.WriteLine("Ovípara");
        }
        public override void Respiracion()
        {
            base.Respiracion();
        }
        #endregion
    }
}

Ya que tenemos nuestra clase base Animal de la cual deriva la clase Vertebrados y que a su vez derivan de esta las clases Anfibios, Aves y Mamiferos, sólo nos queda crear las clases de objetos concretos a esta jerarquía.  Es importante destacar que el nivel de especialización y el nivel de jerarquía dependerá de que tan concreto se desee el diseño de las clases.  También dependerá de la complejidad del problema o software que se desea diseñar.  Esto dependerá completamente del diseñador o arquitecto de software.

Ahora crearemos las clases Gato, Perro, Pollo y Rana los cuales son animales vertebrados pero los primeros dos son mamíferos, el tercero es un ave y el útlimo un anfibio.  Todos comparten ciertas caracteristicas y a su vez cada uno ciertas características que los hacen únicos.  Por el hecho de ser animales todos se alimentan, comunican, se mueven, reproducen y respiran pero cada uno lo hace a su manera.  Como todos son vertebrados todos tienen un esqueleto.  Ahora, el pero y el gato tienen son mamíferos tienen la caracteristica de tener pelo, 4 patas y son de sangre caliente; el pollo es también de sangre caliente pero en vez de pelo tiene plumas y alas que le permite volar, cosa que los dos primeros no pueden. ¿Pueden notar las diferencias y similitudes? Todo esto es posible modelarlo gracias a la herencia y polimorfismo.

Nuestra clase Gato queda de la siguiente manera:

using System;

namespace ReinoAnimal
{
    public class Gato:Mamiferos
    {
        #region [ Constructor ]
        public Gato()
        {
            this.Orden = "Carnivora";
            this.Familia = "Felidae";
            this.Genero = "Felis";
            this.Especie = "F. silvestris";
        }
        #endregion
        public override void Comunicacion()
        {
            Console.WriteLine("Miau! Miau!");
        }
        public override void Movimiento()
        {
            Console.WriteLine("Soy digitígrados ya que camino directamente sobre los dedos de mis patas");
        }
        public void Ronronea()
        {
            Console.WriteLine("Grrrr miau! Grrrr mia!");
        }
    }
}

La clase Perro queda definida asi:

using System;

namespace ReinoAnimal
{
    /// <summary>
    /// Subclase de Mamifero y que heredará los atributos y metodos tanto de Mamifero, Vertebrado y Animal.
    /// 
    /// Aqui escribiremos todas las caracteristicas correspondientes a un perro.
    /// </summary>
    public class Perro : Mamiferos
    {
        #region [ Propiedades ]
        /// <summary>
        /// Un atributo único al perro podría ser la raza
        /// </summary>
        public string Raza { get; set; }
        /// <summary>
        /// De igual manera, puede ser si un perro tiene o no pedigree
        /// </summary>
        public bool Pedigree { get; set; }
        #endregion

        #region [ Constructor ]
        /// <summary>
        /// Constructor base para la clase perro y hereda el constructor de su clase padre
        /// </summary>
        public Perro()
            : base()
        {
            this.Orden = "Carnivora";
            this.Familia = "Caniformia";
            this.Genero = "Canis";
            this.Especie = "Canis lupus";

            Console.WriteLine("Tengo un estrecho lazo con los humanos");
        }

        /// <summary>
        /// Constructor opcional que nos permite especificar el nombre de la raza del perro
        /// </summary>
        /// <param name="pstrRaza">Nombre de la raza del perro</param>
        public Perro(string pstrRaza)
            : this()
        {
            this.Raza = pstrRaza;
        }
        #endregion

        #region [ Metodos  ]
        public override void Alimentacion()
        {
            Console.WriteLine("Soy alimentado por mi dueño a base de croquetas.");
        }
        public override void Comunicacion()
        {
            Console.WriteLine("Guau! Guau!");
        }
        public override void Movimiento()
        {
            Console.WriteLine("Utilizo mis cuatro patas ya sea para correr o caminar.");
        }
        public override void Reproduccion()
        {
            Console.WriteLine("Vivípara");
        }
        public override void Respiracion()
        {
            base.Respiracion();
        }
        #endregion
    }
}

La clase Pollo se ve así:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ReinoAnimal
{
    public class Pollo:Aves
    {
        #region [ Propiedades ]
        #endregion

        #region [ Constructor ]
        /// <summary>
        /// Constructor base para los objetos de tipo Pollo
        /// </summary>
        public Pollo()
            : base()
        {
            this.Orden = "Galliformes";
            this.Familia = "Phasianidae";
            this.Genero = "Gallus";
            this.Especie = "G. gallus";

            Console.WriteLine("La gallina doméstica tal vez sea el ave más numerosa del planeta");
        }
        #endregion

        #region [ Metodos ]
        public override void Alimentacion()
        {
            Console.WriteLine("Soy alimentado por mi dueño en base a una dieta especial para pollo.");
        }

        public override void Comunicacion()
        {
            Console.WriteLine("Pío! Pío!");
        }

        public void Canto()
        {
            Console.WriteLine("quiquiriquí! quiquiriquí!");
        }

        public void Cacarea()
        {
            Console.WriteLine("clo-clo");
        }

        public override void Movimiento()
        {
            base.Movimiento();
        }

        public override void Reproduccion()
        {
            base.Reproduccion();
        }
        #endregion

    }
}

Y finalmente, la clase Rana queda implementada de la siguiente manera:

using System;

namespace ReinoAnimal
{
    public class Rana:Anfibios
    {
        #region [ Constructor ]
        public Rana()
        {
            this.Orden = "Anura";
            this.Familia = "Ranidae";
            this.Genero = "Lithobates";
            this.Especie = "L. clamitans";
        }
        #endregion

        #region [ Métodos ]
        public override void Alimentacion()
        {
            Console.WriteLine("Como insectos y otros invertebrados");
        }
        public override void Comunicacion()
        {
            base.Comunicacion();
        }
        public override void Movimiento()
        {
            Console.WriteLine("Brinco mediante mis ancas");
        }
        public override void Reproduccion()
        {
            base.Reproduccion();
        }
        public override void Respiracion()
        {
            base.Respiracion();
        }
        #endregion
    }
}

No pude subir el codigo fuente dado que wordpress no permite subir archivos *.rar

Si alguien sabe donde puedo alojar el codigo para que lo puedan descargar avisenme porfavor.

Programación Orientada a Objetos (C# y Visual Basic)

Programación orientada a objetos (C# y Visual Basic)

Introducción

Un objeto es una estructura con datos y métodos que manipulan los datos. Si es la primera vez que entra en contacto con la programación orientada a objetos, los siguientes términos y conceptos le ayudarán a hacerse una idea general del tema. Si bien no es necesario dominar la programación orientada a objetos para desarrollar con Visual Studio (C# y Visual Basic) de forma satisfactoria, resulta de gran utilidad, ya que prácticamente la mayoría sino es que todo lo que se hace en Visual Studio (C# y Visual Basic) está asociado con objetos.

Clases y objetos

Las palabras «clase» y «objeto» se usan tanto en la POO que resulta muy fácil confundir los términos. En general, una clase es una representación abstracta de algo, mientras que un objeto es un ejemplo utilizable de ese algo representado por la clase. La única excepción a esta regla la constituyen los miembros de clases compartidas, que se pueden usar tanto en caso de una variable de clase como de una variable de objeto declaradas como el tipo de la clase.

Campos, propiedades, métodos y eventos

Las clases constan de campos, propiedades, métodos y eventos. Los campos y propiedades representan la información que contiene un objeto. Los campos son similares a las variables en cuanto que se pueden leer o definir directamente.

Las propiedades se recuperan y definen igual que los campos, pero se implementan mediante los procedimientos de las propiedades Get y Set, que proporcionan más control sobre el modo en que los valores se definen o se devuelven. La capa de direccionamiento indirecto entre el valor que se almacena y los procedimientos que usan dicho valor ayuda a aislar los datos y permite validar valores antes de que se asignen o se recuperen.

Los métodos representan acciones que puede realizar un objeto. Por ejemplo, un objeto «Automóvil» puede tener definidos los métodos «MotorArranque,» «Tracción» y «Parada». Los métodos se definen al agregar procedimientos (subrutinas o funciones) a la clase.

Los eventos son notificaciones que un objeto recibe de otros objetos u otras aplicaciones o que transmite a ellos. Los eventos permiten a los objetos realizar acciones cada vez que se da un caso concreto.  Dado que Microsoft Windows es un sistema operativo condicionado por eventos, éstos pueden provenir de otros objetos, aplicaciones o acciones del usuario, por ejemplo, al hacer clic con el mouse o presionar teclas.

Encapsulación, herencia y polimorfismo

Los campos, las propiedades, los métodos y los eventos forman sólo la mitad de la ecuación de la programación orientada a objetos. La verdadera programación orientada a objetos requiere que los objetos admitan tres cualidades:

  1. Encapsulación
  2. Herencia
  3. Polimorfismo.

La encapsulación implica el tratamiento de un grupo de propiedades, métodos y otros miembros como una única unidad u objeto. Los objetos pueden controlar el modo en que se cambian las propiedades y se ejecutan los métodos. Por ejemplo, un objeto puede validar valores antes de permitir cambios en propiedades. La encapsulación facilita también el cambio de implementación posterior al permitir ocultar los detalles de implementación de los objetos (ocultación de la información).

Herencia describe la capacidad de crear clases nuevas a partir de una clase existente. La nueva clase hereda todas las propiedades, métodos y eventos de la clase base, y se puede personalizar con propiedades y métodos adicionales.

El polimorfismo implica la posibilidad de tener varias clases que se pueden usar de forma intercambiable, incluso si cada clase implementa las mismas propiedades o métodos de formas distintas. El polimorfismo es esencial para la programación orientada a objetos, ya que permite usar elementos con los mismos nombres, sin importar qué tipo de objeto esté en uso en ese momento.

Sobrecarga, sustitución y ocultación

Sobrecarga, sustitución y ocultación son conceptos similares fáciles de confundir. Aunque las tres técnicas permiten crear miembros con el mismo nombre, hay algunas diferencias importantes.

Los miembros sobrecargados se utilizan para proporcionar distintas versiones de una propiedad o método con el mismo nombre, pero que aceptan distintos números de parámetros, o parámetros con distintos tipos de datos.

Las propiedades y métodos a los que se aplica la técnica de sustitución se usan para reemplazar una propiedad o un método heredados que no resultan apropiados en una clase derivada. Los miembros sustituidos deben aceptar el mismo tipo de datos y número de argumentos. Las clases derivadas heredan miembros sustituidos.

Los miembros a los que se aplica la técnica de ocultación se usan para sustituir localmente un miembro de ámbito más amplio. Cualquier tipo se puede ver ocultado por otro tipo. Por ejemplo, puede declarar una propiedad que oculte un método heredado con el mismo nombre. Los miembros ocultos no se pueden heredar.

C# y Visual Basic y la Programación Orientada a Objetos

Todos los lenguajes administrados de .NET Framework, como Visual Basic y C#, proporcionan plena compatibilidad con la programación orientada a objetos, incluidos la encapsulación, la herencia y el polimorfismo.

Clases y Objetos

Como lo mencionamos arriba, los términos clase y objeto se usan a veces indistintamente pero, en realidad, las clases describen el tipo de los objetos, mientras que los objetos son instancias de clases que se pueden usar. Así, la acción de crear un objeto se denomina creación de instancias.

class SampleClass {}

Tanto Visual Basic como C# también proporcionan una versión ligera de las clases denominadas estructuras, que resultan útiles cuando es necesario crear una matriz grande de objetos y no se desea usar demasiada memoria para ello.

struct SampleStruct {}

Miembros de Clase

Cada clase puede tener distintos miembros de clase, entre los que se incluyen las propiedades que describen los datos de clase, los métodos que definen el comportamiento de la clase y los eventos que proporcionan comunicación entre distintos objetos y clases.

Propiedades y Campos

Los campos y propiedades representan información que contiene un objeto. Los campos se parecen a las variables ya que se pueden leer y establecer directamente.

class SampleClass
{
public string sampleField;
}

Las propiedades tienen procedimientos get y set, que proporcionan un mayor control sobre la forma en que se establecen o devuelven los valores.

Tanto C# como Visual Basic permiten crear un campo privado para almacenar el valor de propiedad o bien usar las denominadas propiedades de implementación automática que crean este campo en segundo plano automáticamente y proporcionan la lógica básica para los procedimientos de propiedad.

Para definir una propiedad implementada automáticamente:

class SampleClass { public int SampleProperty { get; set; } }

Si necesita realizar algunas operaciones adicionales para leer y escribir el valor de propiedad, defina un campo para almacenar el valor de propiedad y proporcione la lógica básica para almacenarlo y recuperar lo:

class SampleClass { private int _sample; public int Sample { // Return the value stored in a field. get { return _sample; } // Store the value in the field. set { _sample = value; } } }

La mayoría de las propiedades tienen métodos o procedimientos tanto para establecer como para obtener el valor de propiedad. Sin embargo, se pueden crear propiedades de solo lectura o solo escritura para restringir su modificación o lectura. En Visual Basic se pueden usar las palabras clave ReadOnly y WriteOnly. En C#, se puede omitir el método de propiedad get o set. Sin embargo, tanto en Visual Basic como en C#, las propiedades implementadas automáticamente no pueden ser de solo lectura o de solo escritura.

Métodos

Un método es una acción que un objeto puede realizar.  En Visual Basic hay dos formas de crear un método: se usa la instrucción Sub si el método no devuelve un valor o bien se usa la instrucción Function si el método devuelve un valor.

Para definir un método para una clase:

class SampleClass { public int sampleMethod(string sampleParam) { // Insert code here } }

Una clase puede tener varias implementaciones o sobrecargas del mismo método que se diferencian en el número de parámetros o de tipos de parámetro.

Para sobrecargar un método:

public int sampleMethod(string sampleParam) {};
public int sampleMethod(int sampleParam) {}

En la mayoría de los casos, un método se declara dentro de una definición de clase. Sin embargo, tanto Visual Basic como C# también admiten los métodos de extensión, que permiten agregar métodos a una clase existente fuera de la definición de la clase en sí.

Constructores

Los constructores son métodos de clase que se ejecutan automáticamente cuando se crea un objeto de un tipo determinado. Normalmente, los constructores inicializan los miembros de datos del nuevo objeto. Un constructor solo puede ejecutarse una vez cuando se crea una clase. Además, el código del constructor siempre se ejecuta antes que cualquier otro código en una clase. Sin embargo, puede crear varias sobrecargas del constructor de la misma forma que para cualquier otro método.

Para definir un constructor para una clase:

public class SampleClass { public SampleClass() { // Add code here } }

Destructores

Los destructores se utilizan para destruir instancias de clases. En .NET Framework, el recolector de elementos no utilizados administra automáticamente la asignación y la liberación de memoria para los objetos administrados en la aplicación. Sin embargo, es posible que aún se necesiten destructores para limpiar cualquiera de los recursos no administrados creados por la aplicación. Solo puede haber un destructor para una clase.

Eventos

Cuando ocurre algo interesante, los eventos habilitan una clase u objeto para notificarlo a otras clases u objetos. La clase que envía (o genera) el evento recibe el nombre de publicador y las clases que reciben (o controlan) el evento se denominan suscriptores.

Clases Anidadas

Una clase definida dentro de otra se denomina anidada. De forma predeterminada, una clase anidada es privada.

class Container { class Nested { // Add code here. } }

Para crear una instancia de la clase anidada, use el nombre de la clase contenedora seguido de un punto y seguido, a continuación, del nombre de la clase anidada:

Container.Nested nestedInstance = new Container.Nested();

Modificadores y Niveles de Acceso

Todas las clases y miembros de clase pueden especificar el nivel de acceso que proporcionan a otras clases mediante los modificadores de acceso.

Están disponibles los siguientes modificadores de acceso:

Visual Basic

C#

Definición

Public public Puede obtener acceso al tipo o miembro cualquier otro código del mismo ensamblado o de otro ensamblado que haga referencia a éste.
Private private Solamente puede obtener acceso al tipo o miembro el código de la misma clase.
Protected protected Solamente puede obtener acceso al tipo o miembro el código de la misma clase o de una clase derivada.
Friend internal Puede obtener acceso al tipo o miembro cualquier código del mismo ensamblado, pero no de un ensamblado distinto.
Protected Friend protected internal Puede obtener acceso al tipo o miembro cualquier código del mismo ensamblado o cualquier clase derivada de otro ensamblado.

Creación de Instacias de Clases

Para crear un objeto, debe crear una o varias instancias de una clase.

SampleClass sampleObject = new SampleClass();

Una vez creadas las instancias de una clase, puede asignar valores a las propiedades y los campos de la instancia, así como invocar métodos de clase.

// Set a property value. sampleObject.sampleProperty = "Sample String"; // Call a method. sampleObject.sampleMethod();

Para asignar valores a las propiedades durante el proceso de creación de instancias de una clase, use los inicializadores de objeto:
// Set a property value.
SampleClass sampleObject = new SampleClass
{ FirstProperty = "A", SecondProperty = "B" };

Clases y Miembros Estáticos

Un miembro estático (compartido en Visual Basic) de la clase es una propiedad, un procedimiento o un campo que comparten todas las instancias de una clase.

Para definir un miembro estático (compartido):

static class SampleClass { public static string SampleString = "Sample String"; }

Para obtener acceso al miembro estático (compartido), use el nombre de la clase sin crear un objeto perteneciente a esta:

Console.WriteLine(SampleClass.SampleString);

Las clases estáticas (compartidas) de C# y los módulos de Visual Basic solamente tienen miembros estáticos (compartidos) y no se pueden crear instancias de los mismos. Además, los miembros estáticos (compartidos) tampoco pueden tener acceso a las propiedades, los campos o los métodos no estáticos (no compartidos).

Tipos Anónimos

Los tipos anónimos permiten crear objetos sin escribir una definición de clase para el tipo de datos. En su lugar, el compilador genera una clase. La clase no tiene ningún nombre que se pueda usar y contiene las propiedades especificadas al declarar el objeto.
// sampleObject is an instance of a simple anonymous type.
var sampleObject =
new { FirstProperty = "A", SecondProperty = "B" };

Herencia

La herencia permite crear una nueva clase que reutiliza, extiende y modifica el comportamiento que se define en otra clase. La clase cuyos miembros se heredan se denomina clase base y la clase que hereda esos miembros se denomina clase derivada. Sin embargo, todas las clases de C# y Visual Basic heredan implícitamente de la clase Object que admite la jerarquía de clases .NET y proporciona servicios de bajo nivel a todas las clases.

Los lenguajes administrados de .NET Framework no admiten la herencia múltiple, es decir, solo se puede especificar una clase base para una clase derivada.

Para heredar de una clase base:
class DerivedClass:BaseClass{}

De forma predeterminada, todas las clases se pueden heredar. Sin embargo, puede especificar si una clase no se debe usar como clase base o bien crear una clase que solo se pueda usar como clase base.

Para especificar que una clase no se puede usar como clase base:
public sealed class A { }

Para especificar que una clase se puede usar solo como clase base y no se pueden crear instancias de esta:
public abstract class B { }

De forma predeterminada, una clase derivada hereda todos los miembros de su clase base. Si desea cambiar el comportamiento del miembro heredado, debe invalidarlo. Es decir, se puede definir una nueva implementación del método, la propiedad o el evento en la clase derivada.

Los siguientes modificadores se utilizan para controlar cómo se reemplazan propiedades y métodos:

Visual Basic C# Definición
Overridable virtual Permite invalidar un miembro de una clase derivada.
Overrides override Invalida un miembro virtual (invalidable) definido en la clase base.
NotOverridable No se admite Impide que un miembro se invalide en una clase heredera.
MustOverride abstract (Referencia de C#) Requiere que se invalide un miembro de clase en la clase derivada.
Shadows new Oculta un miembro heredado de una clase base.

Interfaces

Las interfaces, como las clases, definen un conjunto de propiedades, métodos y eventos. Pero de forma contraria a las clases, las interfaces no proporcionan implementación. Se implementan como clases y se definen como entidades separadas de las clases. Una interfaz representa un contrato, en el cual una clase que implementa una interfaz debe implementar cualquier aspecto de dicha interfaz exactamente como esté definido.

interface ISampleInterface
{
void doSomething();
}

Para implementar una interfaz:
class SampleClass : ISampleInterface
{
void ISampleInterface.SampleMethod()
{
// Method implementation.
}
}

Genéricos

Las clases, las estructuras, las interfaces y los métodos de .NET Framework pueden escribir parámetros que definen los tipos de objetos que estos pueden almacenar o usar. El ejemplo más común de elementos genéricos es una colección, donde se puede especificar el tipo de objetos que se va a almacenar en una colección.

public class SampleGeneric()
{
public T Field;
}

Para crear una instancia de una clase genérica:
SampleGeneric<string> sampleObject = new SampleGeneric<string>();
sampleObject.Field = "Sample string";

Delegados

Un delegado es un tipo que define una firma de método y que puede proporcionar una referencia a cualquier método con una firma compatible. Puede invocar (o llamar) al método a través del delegado. Los delegados se utilizan para pasar métodos como argumentos a otros métodos.

Los controladores de eventos no son más que métodos que se invocan a través de delegados.

Para crear un delegado:
public delegate void SampleDelegate(string str);

Para crear una referencia a un método que coincida con la firma especificada por el delegado:
class SampleClass
{
// Method that matches the SampleDelegate signature.
public static void sampleMethod(string message)
{
// Add code here.
}
// Method that instantiates the delegate.
void SampleDelegate()
{
SampleDelegate sd = sampleMethod;
sd("Sample string");
}
}

Referencias

http://msdn.microsoft.com/es-es/vbasic/ms789107.aspx
http://msdn.microsoft.com/es-es/library/dd460654.aspx

Fundamentos de Programación Orientada a Objetos

Fundamentos de Programación Orientada a Objetos

Cómo dice Laura Leemay en su libro «Aprendiendo Java en 21 días» la POO se parece mucho a la cerveza: la primera vez que la pruebas no te gusta pero si continúas bebiéndola llegas a tomarle cariño.   La POO es una de la ideas de programación más extraordinaria de los últimos años y es una materia que puede ser estudiada y practicada por muchos años, sin embargo, la idea central es simple: organizar los programas de modo que reflejen la forma de organización de los objetos en el mundo real.

Pensando en Objetos

La programación orientada a objetos, es, desde su raíz, una forma de concebir un programa de computadora. Un programa es una serie de instrucciones que le indican a la computadora que hacer. La manera en que la POO ve a un programa es como un conjunto de objetos que operan juntos en formas predefinidas para realizar tareas.

Laura Leemay hace la siguiente analogía entre la POO y el juego de bloques de construcción LEGO. «Para quienes no conocen los bloques LEGO son pequeñas piezas de plástico en varios colores y tamaños.  Estos bloques pequeñas protuberancias redondas en un lado las cuales se ajustan en los huecos de los otros bloques.  La combinación de piezas crea formas más grandes y se pueden usar muchas otras piezas LEGO como llantas, motores, bisagras y poleas.

Con los bloques LEGO se pueden hacer todo tipo de cosas: castillos, automóviles, trailers, etc., casi cualquier cosa que se pueda imaginar. Cada pieza de LEGO es un objeto que se une con otros objetosen forma específica para crear un objeto más grande.

La POO es muy parecida es muy similar a construir estructuras a partir de bloques LEGO. Mediante la POO, todo su programa está formado por objetos diferentes llamados objetos.

Objetos y Clases

Un objeto es un elemento independiente de un programa de computadora, que representa a un grupo asociado de características y esta diseñado para realizar tareas específicas.  A los objetos también se les conoce como instancias.

La programación orientada a objetos se basa en la observación de, en el mundo real, los objetos se construyen a partir de objetos más pequeños. Sin embargo, la capacidad de combinar objetos es sólo un aspecto general de dicha programación. También incluye conceptos y características que hacen que la creación y el uso de objetos sea más sencilla y flexible. La clase es la más importante.

Una clase es una plantilla que se utiliza para crear múltiples objetos con características similares.

Las clases engloban  todas las características de un conjunto particular de objetos.  Cuando escribe un programa en un lenguaje orientado a objetos, usted no define objetos individuales, sino que define clases de objetos.

Por fortuna, no hay que empezar desde cero. La mayoría de los lenguajes orientados a objetos incluyen un grupo de clases que implementan la mayoría de la funcionalidad básica que necesitará.  A estas agrupaciones se les denomina bibliotecas.

Una biblioteca de clases es un grupo de clases diseñadas para su uso con otros programas.

La reutilización es uno de los  beneficios de mayor importancia en la programación orientada a objetos.

Comportamiento y Atributos

En general,  cada clase que escribas esta compuesta de dos componentes:

  1. Atributos
  2. Comportamiento

Atributos

Los atributos son las cosas individuales que diferencían una clase de objetos de otros y determinan la apariencia, estado y otras cualidades de la clase.

También pueden incluir información acerca del estado de un objeto. En una clase, los atributos estan definidos por variables.  Cada objeto puede tener valores distintos para sus variables y a éstas se les denomima variables de instancia.

Una variable de instancia es un elemento de información que define un atributo de un objeto en particular.

La clase del objeto define que tipo de atributo es y cada instancia almacena su propio valor para ese atributo.  A las variables de instancia también se les denomina variables de objeto.

Cada atributo de clase tien una variable correspondiente sencill; al cambiar de valor de la variable puede cambiar ese atributo en un objeto.

Las variables de instancia pueden tomar un valor cuando se crea un objeto y permanece constante a traves de la vida del objeto o bien pueden tomar valores diferentes mientras el objeto se usa en un programa en ejecución.

Para describir toda una clase de objetos se usa otro tipo de atributo en vez de objetos especificos desde la clase. A éstas se les denomina variables de clase.

Una variable de clase es un elemento de información que define un atributo de toda una clase.  La variable aplica para la clase por sí misma y para todas sus instancias, de modo que solo se almacena un valor, no importa cuántos objetos de clase hayan sido creados.

Comportamiento

El comportamiento, es la manera en que una clase de objetos puede hacer cualquier cosa para sí o para otros objetos.

El compartamiento de una clase determina qué objetos de esa clase hacen cambiar sus atributos y tambén qué hacen cuando otros objetos les piden hacer algo.  El comportamiento para una clase de objetos se implementa a través de métodos.

Los métodos son grupo de instrucciones asociadas en una clase de objetos que actúan en si mismos y en otras clases y objetos.  Se usan para realizar tareas específicas, del mismo modo que las funciones se usan en otros lenguajes de programación.

Los objetos se comunican entre sí utilizando métodos.  Una clase o un objeto pueden llamar métodos en otra clase u objeto para muchas razones, incluyendo las siguientes:

  • Para informar un cambio a otro objeto.
  • Para indicar al otro objeto que cambie algo acerca de sí mismo.
  • Para pedir a otro objeto que haga algo.

Así como hay variables de instancia y de clase, también hay métodos de instancia y de clase. Los métodos de instancia, que son tan comunes que sólo se llaman métodos, se aplican a un objeto de la clase. Si el método hace un cambio para un objeto individual, debe de ser un método de instancia. Los métodos de clase aplican pra una clase en sí misma.

Herencia, Interfaces y Paquetes

Herencia

La herencia es uno de los conceptos de mayor importancia en la programación orientada a objetos y tiene un efecto directo en la manera en que diseñas y escribas tus programas.

La herencia es un mecanismo que hace posible que una clase herede todo el comportamiento y los atributos de otra clase.

A través de la herencia, una clase tiene inmediatamente toda la funcionalidad de una clase existente.  Debido a esto, las nuevas clases se pueden crear indicando únicamente en que se diferencian de la clase existente.

A una clase que hereda de otra clase se le denomina subclase y a la clase que proporciona la herencia se le llama superclase.

Una clase puede tener únicamente una superclase, pero cada clase tiene una cantidad ilimitada de subclases. Las subclases reciben por herencia todos los atributos y comportamiento de sus superclases.

En términos prácticos, esto significa que se la superclase tiene comportamiento y atributos que la clase que estas creando necesita, no tendra que redefinirlos o copiar el código para tener el mismo comportamiento y atributos.  Su clase recibe automáticamente todo esto de su superclase, la cual a su vez las obtiene de su superclase y así sucesivamente por toda la jerarquía de clases.  La clase que usted esté creando se convierte en una combinación de todas las características de las clases superiores en la jerarquía, así como de las propias.

Generalmente, en todos los lenguajes que soportan la POO el objeto base de todas las calses es Object. Object es la clase más general de la jerarquía y define el comportamiento y atributos heredados por todas las clases de la biblioteca de clases del lenguaje. Conforme desciende la jerarquía, las clases se construyen para un propósito específico. Una jerarquía de clases define conceptos abstractos en la parte superior de la jerarquía. Estos conceptos se vuelven más concretos conforme desciende la línea de subclases.

La generación de subclases es la creación de una nueva clase que hereda de una clase existente.  La única tarea de la subclase es indicar las diferencias de comportamiento y atributos entre ella y la superclase.

Si tu clase define totalmente un nuevo comportamiento y noes una subclase de otra clase, puede heredar directamente de la clase Object.  De hecho, si crea una definición de clase que no indique una superclase, el lenguaje (ya sea Java, C++, C#, etc)  asume que la clase nueva es herencia directa de Object.

Jerarquía de Clases

Si estás creando un gran conjunto de clases, tendrá sentido que éstas hereen de la jerarquía de clases y conformen una jerarquía por sí mismas.  Organizar clases de esta manera implica invertir un tiempo considerable de planeación, pero las ventajas son las siguientes:

  • La funcionalidad que es común a múltiples clases se puede colocar en superclases, lo que le permite ser utilizada repetidamente en todas las clases inferiores de la jerarquía.
  • Los cambios en la superclase se reflejan automáticamente en todas sus subclases, las subclases de éstas y así sucesivamente. No hay necesidad de cambiar o recompilar cualquiera de las clases inferiores; reciben toda la información a través de la herencia.

¿Cómo funciona la Herencia?

Cuando se crea un objeto nuevo,  el lenguaje registra cada variable definida para el objeto y cada variable definida para cada superclase del objeto. De este modo, todo lo que contienen en las clases se comibina para formar una estructura descriptiva del objeto en uso y cada objeto aporta la información apropiada para su situación.

Los métodos trabajan de manera parecida: los objetos nuevos tienen acceso a todos los nombres de los métodos de su clase y superclase. Esto determina de manera dinámica cuando se usa un método en un programa en ejecución. Si se hace un llamado a un método en un objeto en partitcular,  el interprete del lenguaje primero revisará la clase del objeto para este método. Si no lo encuentra,  lo busca en la superclase y así sucesivamente hasta encontrar la definición del método.

Las cosas se complican cuando una sublase define un método que tiene el mismo nombre, tipo de de valor de retorno y argumentos que otro método definido en una superclase.  En este caso, la definición del método que se localiza primero (comenzando por el fondo de la jerarquía y desplazandose hacia arriba) es la que se ha empleado. En consecuencia, puede crear un método en una clase que evite que se use un método de una superclase.  Para hacerlo, cre un método con el mismo nombre, tipo de valor de retorno y argumentos como el método de la superclase. A este proceso se le denomina sobreposición.

Herencia Sencilla y Múltiple

La Herencia Sencilla es aquella en la que cada clase solo puede tener una superclase (aunque cualquier superclase dada puedar tener múltiples subclases).

La Herencia Múltiple es aquella en la que una clase puede tener mas de una superclase y heredar variables y métodos de forma combinada de todas aquellas superclases.

La herencia múltiple proporciona la estructura para crear clases con casi cual comportamiento imaginable.  En consecuencia, esto complica significativamente las defeniciones de clase y el código necesario para producirlas.  C++ es uno de los lenguajes que soporta este tipo de herencia.  En cambio, Java solo da soporte a la herencia sencilla.

Interfaces

La herencia sencilla hace que la relacion entre clases y su funcionalidad que estas clases implementan sea más fácil de comprender y diseñar.  Sin embargo, también podría ser restrictiva (sobre todo cuando se cuenta con comportamientos similares que necesitan ser duplicados a lo largo de brazos distintos de la jerarquía de clases).  Con el uso de Interfaces, los lenguajes que soportan POO resuelven el problema de comportamiento compartido.

Una Interfaz es un conjunto de métodos que indican que una clase tiene un comportamiento particular además del que hereda de sus superclases.

Paquetes

Los paquetes son una forma de agrupar clases es interfaces asociadas.  Habilitan los grupos de clases para estar disponibles sólo si son necesarios y eliminan los conflictos potenciales entre los nombres de clases en grupos diferentes de clases.

Introducción a la Programación Orientada a Objetos (POO)

Hasta el momento, la definición mas formal que he encontrado es la siguiente de webopedia:

Tipo de programación en el que los programadores definen no sólo el tipo de datos de una estructura de datos, sino también los tipos de operaciones (funciones) que se pueden aplicar a la estructura de datos. De esta manera, la estructura de datos se convierte en un objeto que incluye tanto los datos y funciones.Además, los programadores pueden crear relaciones entre un objeto y otro.

En SerachSOA definen a la programación orientada a objetos como:

Un paradigma de programación organizado en torno a objetos en lugar de acciones y en los datos en vez de la lógica.  Históricamente, un programa ha sido visto como un procedimiento lógico que tomalos datos de entrada, los procesa y produce la salida de datos.

Anteriormente, el desafío de la programación era visto en como escribir la lógica, no la forma de definir los datos.  La programación orientada a objetos considera que lo que realmente importa son los objetos que queremos manipular en lugar de la lógica requerida para manipularlos.

El primer paso en la programación orientada a objetos es el de identificar todos los objetos que desea manipular y cómo se relacionan entre sí, un ejercicio a menudo conocido como el modelado de datos.  Una vez que haya identificado un objeto, se generaliza como una clase de objetos y define el tipo de datos que contiene y de cualquier secuencia lógica que pueda manipular.  Cada secuencia lógica distinta se conoce como un método. Una instncia real de una clase es llamada  objeto o en algunos entornos, una instancia de una clase.  La instancia de objeto o una clase es lo que se ejecuta en la computadora. Sus métodos proporcionan las instrucciones de computadora y las características del objeto proporcionan los datos pertinentes.

Si es la primera vez que entras en contacto con la programación orientada a objetos, los siguientes términos y conceptos te ayudarán a hacerse una idea general del tema. Los objetos son entidades que combinan estado (atributo)comportamiento (método)identidad. Los objetos de software se utilizan para modelar objetos del mundo real que encuentras en tu vida cotidiana. Es una instancia a una clase.  Una clase es un modelo o prototipo de los objetos que se crean. La herencia es un mecanismo poderoso y natural para la organización y la arquitectura de su software. Una interfaz es un contrato entre una clase y el mundo exterior. Cuando una clase implementa una interfaz, se compromete a proporcionar el comportamiento establecido por esa interfaz.  Un paquete es un espacio de nombres para la organización de clases e interfaces de una manera lógica.  La organización de tu código en paquetes de software hace que grandes proyectos sean más fácil de administrar.

Las principales características de la programación orientada a objetos son:

  1. La Abstracción la cual denota las características esenciales de un objeto. El proceso de abstracción permite seleccionar las características relevantes dentro de un conjunto e identificar comportamientos comunes para definir nuevos tipos de entidades en el mundo real. La abstracción es clave en el proceso de análisis y diseño orientado a objetos, ya que mediante ella podemos llegar a armar un conjunto de clases que permitan modelar la realidad o el problema que se quiere atacar.
  2. El Encapsulamiento el cual permite reunir a todos los elementos que pueden considerarse pertenecientes a una misma entidad, al mismo nivel de abstracción, facilitando la cohesión de los componentes del sistema.
  3. Se denomina Modularidad a la propiedad que permite subdividir una aplicación en partes más pequeñas (llamadas módulos), cada una de las cuales debe ser tan independiente como sea posible de la aplicación en sí y de las restantes partes. Estos módulos se pueden compilar por separado, pero tienen conexiones con otros módulos.
  4. Ocultación. Cada objeto está aislado del exterior, es un módulo natural, y cada tipo de objeto expone una interfaz a otros objetos que especifica cómo pueden interactuar con los objetos de la clase. El aislamiento protege a las propiedades de un objeto contra su modificación por quien no tenga derecho a acceder a ellas, solamente los propios métodos internos del objeto pueden acceder a su estado. Esto asegura que otros objetos no pueden cambiar el estado interno de un objeto de maneras inesperadas, eliminando efectos secundarios e interacciones inesperadas.
  5. El Polimorfismo permite comportamientos diferentes, asociados a objetos distintos, pueden compartir el mismo nombre, al llamarlos por ese nombre se utilizará el comportamiento correspondiente al objeto que se esté usando. O dicho de otro modo, las referencias y las colecciones de objetos pueden contener objetos de diferentes tipos, y la invocación de un comportamiento en una referencia producirá el comportamiento correcto para el tipo real del objeto referenciado.
  6. Herencia. Las clases no están aisladas, sino que se relacionan entre sí, formando una jerarquía de clasificación. Los objetos heredan las propiedades y el comportamiento de todas las clases a las que pertenecen. La herencia organiza y facilita el polimorfismo y el encapsulamiento permitiendo a los objetos ser definidos y creados como tipos especializados de objetos preexistentes. Estos pueden compartir (y extender) su comportamiento sin tener que volver a implementarlo. Esto suele hacerse habitualmente agrupando los objetos en clases y estas en árbolesenrejados que reflejan un comportamiento común. Cuando un objeto hereda de más de una clase se dice que hay herencia múltiple.
  7. La Recolección de Basura es la técnica por la cual el entorno de objetos se encarga de destruir automáticamente, y por tanto desvincular la memoria asociada, los objetos que hayan quedado sin ninguna referencia a ellos. Esto significa que el programador no debe preocuparse por la asignación o liberación de memoria, ya que el entorno la asignará al crear un nuevo objeto y la liberará cuando nadie lo esté usando.
Referencias:
http://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos
http://www.webopedia.com/TERM/O/object_oriented_programming_OOP.html
http://searchsoa.techtarget.com/definition/object-oriented-programming
http://en.wikipedia.org/wiki/Object-oriented_programming
http://download.oracle.com/javase/tutorial/index.html