¿Puede alguien explicarme métodos anónimos?
Delphi 2009, entre algunas cosas interesantes, también tiene métodos anónimos. He visto los ejemplos y las publicaciones de blog sobre métodos anónimos, pero aún no los entiendo. ¿Alguien puede explicar por qué debería estar emocionado?
7 answers
Solo piense en el típico código de devolución de llamada donde necesita tener datos disponibles para la devolución de llamada. A menudo estos datos son necesarios para la devolución de llamada solo, sin embargo, tienes que saltar a través de una serie de aros para llegar allí sin tener que renunciar a las prácticas no-OOP-friendly como variables globales. Con métodos anónimos, los datos pueden permanecer donde están, no tiene que extender innecesariamente su alcance o copiarlos en algún objeto auxiliar. Simplemente escriba su código de devolución de llamada en el lugar como un método anónimo y puede acceder y manipular completamente todas las variables locales en el sitio donde se define el método anónimo (¡no donde se llama!).
Hay otros aspectos de los métodos anónimos, lo más obvio es el hecho de que son, bueno: anónimos, pero este es el que realmente los hizo hacer "clic" para mí...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-05 14:00:44
Por favor, echa un vistazo a cierres.
Las funciones anónimas de Delphi son cierres.
Estos se crean dentro de otras funciones y como tales tiene acceso al alcance de esa función. Esto es aún así si la función anónima se asigna a un parámetro de función que se llama después de que se llama a la función original. (Crearé un ejemplo en un momento).
type
TAnonFunc = reference to procedure;
TForm2 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
F1 : TAnonFunc;
F2 : TAnonFunc;
end;
procedure TForm2.Button1Click(Sender: TObject);
var
a : Integer;
begin
a := 1;
F1 := procedure
begin
a := a + 1;
end;
F2 := procedure
begin
Memo1.Lines.Add(IntToStr(a));
end;
end;
El método anterior asigna dos funciones anónimas a los campos F1 y F2. El primero aumenta la variable local y la segunda muestra el valor de la variable.
procedure TForm2.Button2Click(Sender: TObject);
begin
F1;
end;
procedure TForm2.Button3Click(Sender: TObject);
begin
F2;
end;
Ahora puede llamar a ambas funciones, y acceden a la misma a. Así que llamar a F1 dos veces y a F2 una vez muestra un 3. Por supuesto, este es un ejemplo simple. Pero se puede ampliar a código más útil.
En el entorno multi threading, se pueden usar funciones anónimas en una llamada para Sincronizar, lo que elimina la necesidad de innumerables métodos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-01 22:11:13
Puede ser este ejemplo puede ser de algún valor para usted. Aquí voy a implementar una lista de visualización ampliable para dibujar en un TCanvas sin declarar diferentes tipos de clases de visualización. También hace un uso intensivo de genéricos. Supongamos que tenemos un TForm con un TPaintBox y una TTrackBar en él...
type
TDisplayProc = TProc<TCanvas>;
type
TFrmExample3 = class(TForm)
pbxMain: TPaintBox;
trkZoom: TTrackBar;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure pbxMainClick(Sender: TObject);
procedure pbxMainMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure pbxMainPaint(Sender: TObject);
procedure trkZoomChange(Sender: TObject);
private
FDisplayList: TList<TDisplayProc>;
FMouseX: Integer;
FMouseY: Integer;
FZoom: Extended;
procedure SetZoom(const Value: Extended);
protected
procedure CreateCircle(X, Y: Integer);
procedure CreateRectangle(X, Y: Integer);
function MakeRect(X, Y, R: Integer): TRect;
public
property Zoom: Extended read FZoom write SetZoom;
end;
implementation
{$R *.dfm}
procedure TFrmExample3.PaintBox1Paint(Sender: TObject);
var
displayProc: TDisplayProc;
begin
for displayProc in FDisplayList do
displayProc((Sender as TPaintBox).Canvas);
end;
procedure TFrmExample3.CreateCircle(X, Y: Integer);
begin
FDisplayList.Add(
procedure (Canvas: TCanvas)
begin
Canvas.Brush.Color := clYellow;
Canvas.Ellipse(MakeRect(X, Y, 20));
end
);
end;
procedure TFrmExample3.CreateRectangle(X, Y: Integer);
begin
FDisplayList.Add(
procedure (Canvas: TCanvas)
begin
Canvas.Brush.Color := clBlue;
Canvas.FillRect(MakeRect(X, Y, 20));
end
);
end;
procedure TFrmExample3.FormCreate(Sender: TObject);
begin
FDisplayList := TList<TDisplayProc>.Create;
end;
procedure TFrmExample3.FormDestroy(Sender: TObject);
begin
FreeAndNil(FDisplayList);
end;
function TFrmExample3.MakeRect(X, Y, R: Integer): TRect;
begin
Result := Rect(Round(Zoom*(X - R)), Round(Zoom*(Y - R)), Round(Zoom*(X + R)), Round(Zoom*(Y + R)));
end;
procedure TFrmExample3.pbxMainClick(Sender: TObject);
begin
case Random(2) of
0: CreateRectangle(Round(FMouseX/Zoom), Round(FMouseY/Zoom));
1: CreateCircle(Round(FMouseX/Zoom), Round(FMouseY/Zoom));
end;
pbxMain.Invalidate;
end;
procedure TFrmExample3.pbxMainMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
FMouseX := X;
FMouseY := Y;
end;
procedure TFrmExample4.SetZoom(const Value: Extended);
begin
FZoom := Value;
trkZoom.Position := Round(2*(FZoom - 1));
end;
procedure TFrmExample4.trkZoomChange(Sender: TObject);
begin
Zoom := 0.5*(Sender as TTrackBar).Position + 1;
pbxMain.Invalidate;
end;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-02 18:13:35
La gente ya ha proporcionado el código, así que solo enumeraré algunos lugares donde pueden ser útiles.
Digamos que tienes algún código GUI. Normalmente, para algo como el controlador onclick de un botón, debes proporcionar una función a la que se llamará cuando se haga clic en ese botón. Sin embargo, digamos que todo lo que la función tiene que hacer es algo simple como abrir un cuadro de mensaje o establecer un campo en algún lugar. Digamos que tienes docenas de estos botones a lo largo de tu código. Sin funciones anónimas, tiene que tener toneladas de funciones llamadas " OnButton1Click," "OnExitButtonClick," etc, que probablemente desordenará su código... o puede crear funciones anónimas que se adjuntan inmediatamente a estos eventos, y ya no tiene que preocuparse por ellos.
Otro uso es la programación funcional. Digamos que tienes una lista de números. Usted quiere recuperar sólo los números que son divisibles por tres. Probablemente hay una función llamada filter
que toma una función que devuelve un booleano y un list, y devuelve una nueva lista que contiene solo los elementos de la primera lista que, cuando se pasan a la función, devuelven True. Ejemplo:
filter(isOdd, [1, 2, 3, 5, 6, 9, 10]) --> [1, 3, 5, 9]
Sería molesto ser forzado a definir una función "isDivisibleByThree", luego pasarla a filter, por lo que otro uso para funciones anónimas aquí sería simplemente crear rápidamente una función que no necesitará en ningún otro lugar y pasarla a filter.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-02 18:24:39
Estoy respondiendo a mi propia pregunta, pero encontré una buena explicación de los métodos anónimos aquí ¿Puede su lenguaje de programación hacer esto?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-02 23:18:40
Supongo (no conozco Delphi) esto implica que ahora puedes crear funciones como una especie de objeto de datos. Esto significa que puede, por ejemplo, pasar funciones como parámetros a otras funciones. Ejemplo: Una función de ordenación puede tomar una función de comparación como parámetro, por lo que es mucho más versátil.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-01 21:48:58
Los métodos anónimos son útiles en la programación funcional, pero también pueden ayudarle a escribir un código más compacto en la programación estructurada. Roscado, por ejemplo: http://blogs.codegear.com/abauer/2008/09/08/38868
Otros casos de uso para su' emoción':): http://delphi.fosdal.com/2008/08/anonymous-methods-when-to-use-them.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-02 08:02:19