C # conoce dos términos, delegate
y event
. Comencemos con el primero.
Delegar
A delegate
es una referencia a un método. Al igual que puede crear una referencia a una instancia:
MyClass instance = myFactory.GetInstance();
Puede usar un delegado para crear una referencia a un método:
Action myMethod = myFactory.GetInstance;
Ahora que tiene esta referencia a un método, puede llamar al método a través de la referencia:
MyClass instance = myMethod();
¿Pero por qué lo harías? También puedes llamar myFactory.GetInstance()
directamente. En este caso puedes. Sin embargo, hay muchos casos para pensar en los que no desea que el resto de la aplicación tenga conocimiento myFactory
o llamemyFactory.GetInstance()
directamente.
Una obvia es si usted quiere ser capaz de reemplazar myFactory.GetInstance()
a myOfflineFakeFactory.GetInstance()
partir de un lugar central (aka Factory Method ).
Patrón de método de fábrica
Entonces, si tiene una TheOtherClass
clase y necesita usarla myFactory.GetInstance()
, así es como se verá el código sin delegados (deberá informar TheOtherClass
sobre el tipo de su myFactory
):
TheOtherClass toc;
//...
toc.SetFactory(myFactory);
class TheOtherClass
{
public void SetFactory(MyFactory factory)
{
// set here
}
}
Si usaría delegados, no tiene que exponer el tipo de mi fábrica:
TheOtherClass toc;
//...
Action factoryMethod = myFactory.GetInstance;
toc.SetFactoryMethod(factoryMethod);
class TheOtherClass
{
public void SetFactoryMethod(Action factoryMethod)
{
// set here
}
}
Por lo tanto, puede asignar un delegado a otra clase para que lo use, sin exponer su tipo a ellos. Lo único que está exponiendo es la firma de su método (cuántos parámetros tiene y tal).
"Firma de mi método", ¿dónde escuché eso antes? ¡Oh sí, interfaces! Las interfaces describen la firma de toda una clase. ¡Piense en los delegados como describiendo la firma de un solo método!
Otra gran diferencia entre una interfaz y un delegado es que cuando escribe su clase, no tiene que decirle a C # "este método implementa ese tipo de delegado". Con las interfaces, debe decir "esta clase implementa ese tipo de interfaz".
Además, una referencia de delegado puede (con algunas restricciones, ver más abajo) hacer referencia a múltiples métodos (llamados MulticastDelegate
). Esto significa que cuando llama al delegado, se ejecutarán varios métodos adjuntos explícitamente. Una referencia de objeto siempre puede hacer referencia a un solo objeto.
Las restricciones para a MulticastDelegate
son que la firma (método / delegado) no debe tener ningún valor de retorno ( void
) y las palabras clave out
y ref
no se utiliza en la firma. Obviamente, no puede llamar a dos métodos que devuelven un número y esperan que devuelvan el mismo número. Una vez que la firma cumple, el delegado es automáticamente a MulticastDelegate
.
Evento
Los eventos son solo propiedades (como get; set; propiedades para campos de instancia) que exponen la suscripción al delegado de otros objetos. Estas propiedades, sin embargo, no admiten get; set ;. En cambio, admiten agregar; eliminar;
Entonces puedes tener:
Action myField;
public event Action MyProperty
{
add { myField += value; }
remove { myField -= value; }
}
Uso en la interfaz de usuario (WinForms, WPF, UWP, etc.)
Entonces, ahora sabemos que un delegado es una referencia a un método y que podemos tener un evento para que el mundo sepa que pueden darnos sus métodos para que nuestro delegado nos haga referencia, y somos un botón de interfaz de usuario, entonces: puede preguntar a cualquier persona interesada en si se me hizo clic, para registrar su método con nosotros (a través del evento que expusimos). Podemos usar todos los métodos que nos fueron proporcionados y hacer referencia a ellos por nuestro delegado. Y luego, esperaremos y esperaremos ... hasta que aparezca un usuario y haga clic en ese botón, entonces tendremos suficientes razones para invocar al delegado. Y debido a que el delegado hace referencia a todos los métodos que nos han dado, se invocarán todos esos métodos. No sabemos qué hacen esos métodos, ni sabemos qué clase implementa esos métodos. Lo único que nos importa es que alguien esté interesado en que se haga clic en nosotros,
Java
Lenguajes como Java no tienen delegados. Usan interfaces en su lugar. La forma en que lo hacen es pedirle a cualquiera que esté interesado en 'que se nos haga clic', que implemente una determinada interfaz (con un cierto método al que podamos llamar), y luego darnos la instancia completa que implementa la interfaz. Mantenemos una lista de todos los objetos que implementan esta interfaz y podemos llamar a su 'cierto método que podemos llamar' cada vez que hacemos clic.