Implementar una interface es establecer un contrato entre dos bloques de código, donde el bloque que implementa la interface se compromete a implementar concretamente los métodos que la interface implementada define. 

En principio esto a veces suena raro. La pregunta que surge es ¿no me estaré complicando la vida?… depende… 

Supongamos que en el marco de un proceso tenemos un conjunto de objetos heterogéneos que desconocemos. Algunos tienen un método de serialización de nombre Save, si el método existe, es el encargado de persistit al objeto. Si no existe el método Save, el objeto se persiste en base de datos por medio de otro método.

La pregunta es ¿cómo preguntar, en tiempo de ejecución, si un objeto implementa un método de un determinado nombre?Lo que sigue intenta responder esto. Para desarrollar este ejemplo, hay que abrir Visual Studio y crear un proyecto de Windows de Consola en Visual Basic o C#.

Ahora creamos la interface ISerializable, que contiene la función Save que devuelve un boolean: 

[VB]

Public Interface ISerializable   

    Function Save() As Boolean

End Interface 

[C#]

using System; 

interface ISerializable

    {

        bool Save();

    }

Por convención a los nombres de las interfaces se les prefija una “I” para una mejor identificación. 

Luego vamos a crear una clase, de nombre Controlcito, con una única propiedad llamada Datos de tipo string: 

[VB]

Public Class Controlcito

    Private mDatos As String

    Public Property Datos() As String

        Get

            Return mDatos

        End Get

        Set(ByVal value As String)

            mDatos = value

        End Set

    End Property

End Class 

[C#]

using System;

     public class Controlcito

    {

        protected string Data;

        public string data

        {

            get

            {

                 return this.Data;

            }

            set

            {

                this.Data = value;

            }

        }

    }

 Defino ahora un control, con nombre miControl, que herede de Controlcito e implemente la interface ISerializable 

[VB]

Public Class miControl

    Inherits Controlcito

    Implements ISerializable

     Public Sub New()

        Datos = «Estos son los datos de prueba…»

     End Sub

     Public Function Save() As Boolean

         Implements ISerializable.Save

        Console.WriteLine(«Grabando…{0}», Datos)

        Return True

    End Function

End Class 

 

[C#]

using System;

class miControl : Controlcito, IValidate, ISerializable 

    {

        public miControl()

        {

            data = «Mis datos de prueba.»;

        }

         public bool Save()

        {

            Console.WriteLine(«Grabando…{0}», data);

            return true;

        }

    }

De esta forma queda implementado, efectivamente, el método Save de la interface ISerializable. Verán que al tipear la linea de código referida a la implementación de la interface, cuando se hace click en Enter, Visual Studio escribe el encabezado de la función que define la interface.

Ya sabemos cómo implementar una Interface.

Ahora el problema es saber, programáticamente, si una clase implementa una Interface. Para el ejemplo que estamos viendo, en términos concretos, es saber si la clase tiene implementado un método Save, en otras palabras, si la clase implementa algún método de serialización.

Entonces vamos a escribir la aplicación que se lanzará en consola, la llamamos App 

[VB]

Module App

    Sub Main()

        Console.WriteLine(«Versión Visual Basic»)

        Dim miControl As New miControl

        Dim ser As ISerializable = DirectCast(miControl, ISerializable)

        Dim exito As Boolean = ser.Save

        Console.WriteLine(«La validación de ‘{0}’ {1} fue correcta», miControl.Datos, IIf(exito, «», «no»))

    End Sub

    Console.ReadLine()

End Module 

 

[C#]

class App

    {

        public static void Main()

        {

            Console.WriteLine(«Versión C#»);

            miControl miControl = new miControl();

            ISerializable ser = (ISerializable)miControl;

            bool exito = ser.Save();

            Console.WriteLine(«La validación de ‘{0}’ {1} fue correcta», miControl.data, (true == exito ? «» : «no»));

        }

        Console.ReadLine();

    }

Esto parece funcionar, pero si la interface no está implementada DirectCast(miControl, ISerializable), en VB, o (ISerializable)miControl, en C#, ambos, en ese caso dan error.

La forma correcta de preguntar es TypeOf (miControl) Is ISerializable, en VB, o miControl Is ISerializable, en C#. Veamos:

[VB]

Module App

    Sub Main()

        Console.WriteLine(«Versión Visual Basic»)

        Dim miControl As New miControl

        If TypeOf (miControl) Is ISerializable Then

            Dim ser As ISerializable = DirectCast(miControl, ISerializable)

            Dim otroExito As Boolean = ser.Save

            Console.WriteLine(«Los Datos de ‘{0}’ {1} se han guardado satisfactoriamente», miControl.Datos, IIf(otroExito, «», «no»))

        End If

        Console.ReadLine()

    End Sub

End Module 

[C#]

class App

    {

        public static void Main()

        {

            Console.WriteLine(«Versión C#»);

            miControl miControl = new miControl();

            if (miControl is ISerializable)

            {

                ISerializable ser = (ISerializable)miControl;

                bool otroExito = ser.Save();

                Console.WriteLine(«Los Datos de ‘{0}’ {1} se han guardado satisfactoriamente», miControl.data, (true == otroExito ? «» : «no»));

            }

            Console.ReadLine();

        }

    }

Esto funciona correctamente en ambos lenguajes. Pero existe una forma optimizada, en términos de código MSIL.

En VB se usa TryCast que evalúa si la interface está implementada, si no lo está, no devuelve error sino Nothing. En C# esto es análogo con el operador as. 

[VB]

Module App

    Sub Main()

        Console.WriteLine(«Versión Visual Basic»)

        Dim miControl As New miControl

        Dim serial As ISerializable = TryCast(miControl, ISerializable)

        If Not serial Is Nothing Then

            Dim otroExitoMas As Boolean = serial.Save

            Console.WriteLine(«Los Datos de ‘{0}’ {1} se han guardado satisfactoriamente, con una versión optimizada», miControl.Datos, IIf(otroExitoMas, «», «no»))

        End If

        Console.ReadLine()

    End Sub

End Module 

 

[C#]

class App

    {

        public static void Main()

        {

            Console.WriteLine(«Versión C#»);

            miControl miControl = new miControl();

            ISerializable serial = miControl as ISerializable;

            if (null != serial)

            {

                bool otroExitoMas = serial.Save();

                Console.WriteLine(«Los Datos de ‘{0}’ {1} se han guardado satisfactoriamente, con una versión optimizada», miControl.data, (true == otroExitoMas ? «» : «no»));

            }

            Console.ReadLine();

        }

    }

La solución, con los proyectos de ejemplo pueden descargarse de Interfaces.zip

Ojalá haya servido de algo. 🙂