You are currently browsing the category archive for the 'Interfaces' category.
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.
