Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 23-08-2010
Avatar de mlara
[mlara] mlara is offline
Miembro Premium
 
Registrado: jun 2003
Ubicación: Colombia
Posts: 667
Poder: 21
mlara Va por buen camino
Función virtual...

Como ejemplo, cuando uso un objeto de la VCL, sé que puedo hacer algo como esto:

Código:
procedure TForm.MiObjetoOnEvento1(Sender: TObject);
begin
  ...
end;

procedure MiEventoAlternativo1(Sender: TObject);
begin
  ...
end;

procedure TForm.Button1Click(Sender: TObject);
begin
  ...
  MiObjeto.Evento1 := nil;
  ...
  // Aquí hago algo que involucra a MiObjeto y quiero evitar que se ejecute
  // el código del evento 1, pero más adelante sí necesito que el código
  // se ejecute, por lo cual hago nuevamente la asignación.
  ...
  MiObjeto.Evento1 := MiEventoOnEvento1;
  ...
  // Luego, necesito que el código a ejecutar sea otro, pero ante el mismo
  // evento, por lo cual hago esta otra asignación.
  ...
  MiObjeto.Evento1 := MiEventoAlternativo1;
  ...
end;
Esto lo he hecho y funciona perfectamente.

Ahora requiero declarar una función en el código de una forma (TForm), y luego, al ejecutar esa función, dependiendo de cierto parámetro, quiero que se ejecute un código diferente reasignando el código de la función, así:

Código:
if Tag = 1 then
  MiFuncion := MiFuncion1
else if Tag = 2 then
  MiFuncion := MiFuncion2
else if Tag = 3 then
  MiFuncion := MiFuncion3
...

// Todas las funciones son de tipo booleano, así que...
if MiFuncion then
  ...
else
  ...
La cuestión es que esto último no he podido hacerlo. El ejemplo de arriba me hace suponer que sí puedo asignar una función definida (MiEventoOnEvento1 o MiEventoAlternativo1) a una función declarada dentro de una clase (Evento1), pero como ven tengo problemas...

Sé también que podría implementar un código alternativo, pero de verdad requiero una solución como la solicitada.

Gracias, si alguien puede colaborarme.
__________________
...y mañana caminaré por las calles pasando inadvertido, como siempre.

Última edición por mlara fecha: 23-08-2010 a las 19:19:37.
Responder Con Cita
  #2  
Antiguo 23-08-2010
Avatar de Lord Delfos
Lord Delfos Lord Delfos is offline
Miembro
 
Registrado: ene 2008
Ubicación: Tandil, Argentina
Posts: 558
Poder: 17
Lord Delfos Va por buen camino
Hola mlara.

Te olvidaste de poner cuál es el error que recibís del compilador, pero me jugaría la cabeza a que el problema es de tipos incorrectos.

Esto se debe a que el compilador interpreta que vos querés llamar a la función y asignarle el resultado a tu evento. Solución:

Código Delphi [-]
MiFuncion:= @MiFuncion1;

El arroba le dice a Delphi explicitamente que vos querés asignar la dirección de memoria de tu función, y no el resultado de llamarla

Espero te sirva. Saludongos.
Responder Con Cita
  #3  
Antiguo 23-08-2010
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
Hola, creo que el error lo tienes por definicion de tipos. Antes que nada, lo que estas comentando con los eventos es posible porque son procedures, no estoy seguro si lo que te pondre va tambien con funciones, si eso lo pruebas

Código Delphi [-]

type TMiTipoDeFuncion = function (Sender : TObject) : boolean of object

...

function TForm1.F1(Sender : TObject): boolean;
begin
...
end;

function TForm1.F2(Sender : TObject) : boolean;
begin
...
end;

var
  MiFuncion : TMiTipoDeFuncion;
begin
case Switch of 
1 : MiFuncion := F1;
2 : MiFuncion := F2;
...
end;

if MiFuncion(Argumento) = true then ...

Algo asi. No se si funcionaria porque creo que los punteros a funciones, no a procedures, se aplican tal como te dice Lord Delfos. De todas maneras, este codigo siguiente si que te funcionaria :

Código Delphi [-]

type TMiProcedureBoolean : procedure (Sender : TObject; var b : boolean) of object;

...

procedure TForm1.P1(sender : TObject;var b : boolean);
begin
...
   b := resultado
end;

...

var
   MiProcedure : TMiProcedureBoolean;
   Resultado : boolean;
begin

case Switch of 
1 : MiProcedure := P1;
2 : MiProcedure := P2;
...
end;

MiProcedure(self,Resultado);

if Resultado then ...

Espero te sirva de ayuda. Un saludo.
Responder Con Cita
  #4  
Antiguo 23-08-2010
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola mlara.

Me llama la atención que no funcione... debería. Por lo que hice una prueba simple y me funciona bién.

Aunque no lo aclaras, creo que no te dá un error sino que simplemente no se ejecuta el código...
Me parece que el problema lo tenés en la evaluación del Tag.

Probá esto:
.Un PopupMenu asignado a la propiedad PopupMenu del Form.
.En el PopupMenu,tres Menuitems 'nil', 'OnChange1', 'Onchange2' y en sus eventos OnClick asignado: itOnChangeClick
.Por último un Edit.
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, 
 Controls, Forms,  Dialogs, StdCtrls, Menus;

type
  TForm1 = class(TForm)
    Edit: TEdit;
    PopupMenu1: TPopupMenu;
    itNil: TMenuItem;
    itOnChange1: TMenuItem;
    itOnChange2: TMenuItem;
    procedure itOnChangeClick(Sender: TObject);
  private
    procedure EditChange1(Sender: TObject);
    procedure EditChange2(Sender: TObject);
  public
  end;

var
  Form1: TForm1;

implementation {$R *.dfm}

procedure TForm1.EditChange1(Sender: TObject);
begin
  ShowMessage('OnChange 1')
end;

procedure TForm1.EditChange2(Sender: TObject);
begin
  ShowMessage('OnChange 2');
end;

procedure TForm1.itOnChangeClick(Sender: TObject);
begin
  case TMenuItem(Sender).Tag of
    1: Edit.OnChange:= nil;
    2: Edit.OnChange:= EditChange1;
    3: Edit.OnChange:= EditChange2;
  end;
end;

end.

Tecleá en el edit seleccionando las opciones del PopupMenu...


Saludos.

Última edición por ecfisa fecha: 23-08-2010 a las 21:41:46.
Responder Con Cita
  #5  
Antiguo 23-08-2010
Avatar de delphi.com.ar
delphi.com.ar delphi.com.ar is offline
Federico Firenze
 
Registrado: may 2003
Ubicación: Buenos Aires, Argentina *
Posts: 5.932
Poder: 27
delphi.com.ar Va por buen camino
Cita:
Empezado por mlara Ver Mensaje
Ahora requiero declarar una función en el código de una forma (TForm), y luego, al ejecutar esa función, dependiendo de cierto parámetro, quiero que se ejecute un código diferente reasignando el código de la función, así:
En Delphi puedes tener referencia tanto a Métodos como a procedimientos regulares sin ningún problema, solo tienes que tener en cuenta que la lista de argumentos y el resultado de las funciones debe coincidir con el tipo especificado, sino se volcarán datos inválidos en los esperados.

Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TRegularProcedure = procedure;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    procedure Hola(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure Chau;
begin
  ShowMessage('Chau!');
end;


{ TForm1 }

procedure TForm1.Hola(Sender: TObject);
begin
  ShowMessage('Hola');
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  AMetodo: TNotifyEvent;
  AProcedimiento: TRegularProcedure;
begin
  AMetodo := Hola;
  AMetodo(nil);

  AProcedimiento := Chau;
  AProcedimiento;
end;

end.

Saludos!
__________________
delphi.com.ar

Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla.
Responder Con Cita
  #6  
Antiguo 24-08-2010
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

Y ya que estamos con los punteros a funciones y a métodos, este es el ejemplo anterior implementado con
puntero a método. (como para no dejar las cosas a medias... )

Código Delphi [-]
type
  TEventoPtr= procedure(Sender: TObject) of object;
  TForm1 = class(TForm)
    Edit1: TEdit;
    PopupMenu1: TPopupMenu;
    Nil1: TMenuItem;
    ProcA1: TMenuItem;
    ProcB1: TMenuItem;
    procedure FormCreate(Sender: TObject);
  private
    procedure Proc_A(Sender: TObject);
    procedure Proc_B(Sender: TObject);
  public
    EventoPtr: TEventoPtr;
    procedure MenuItmOnClick(Sender: TObject);
  end;
var
  Form1: TForm1;

implementation {$R *.dfm}

procedure TForm1.Proc_A(Sender: TObject);
begin
  ShowMessage('Proc_A');
end;

procedure TForm1.Proc_B(Sender: TObject);
begin
  ShowMessage('Proc_B');
end;

procedure TForm1.MenuItmOnClick(Sender: TObject);
begin
  case TMenuItem(Sender).Tag of
    1: Edit1.OnChange:= nil;
    2: Edit1.OnChange:= Proc_A;
    3: Edit1.OnChange:= Proc_B;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  EventoPtr:= MenuItmOnClick;
  for i:= 0 to PopupMenu1.Items.Count -1 do
     PopupMenu1.Items[i].OnClick:= EventoPtr;
end;

Saludos.

Última edición por ecfisa fecha: 24-08-2010 a las 01:01:11.
Responder Con Cita
  #7  
Antiguo 24-08-2010
Avatar de mlara
[mlara] mlara is offline
Miembro Premium
 
Registrado: jun 2003
Ubicación: Colombia
Posts: 667
Poder: 21
mlara Va por buen camino
Thumbs up Perfecto...

Agradezco a todos su colaboración... fue muy útil, tanto que a partir de ahí tomé la decisión de usar el siguiente código:

Código Delphi [-]
function MyFunc1: Boolean;
begin
  ...
end;

function MyFunc2: Boolean;
begin
  ...
end;

procedure TForm.OnEvent(Sender: TObject); // En realidad se trata de cualquier procedimiento o función. OnEvent supone un evento cualquiera.
var
  MyFunc: function(): Boolean;
begin
  if Condition = 1 then
    MyFunc := MyFunc1
  else
    MyFunc := MyFunc2;
  ...
  if MyFunc then
    ...
  ...
end;

... y funciona a la perfección. Prácticamente el problema era la declaración, incluso el lugar de la declaración. Me estaba enredando un poco con la teoría de funciones virtuales, pero como no estaba derivando ninguna clase me quedé barado, pero ahora todo está bien.

Gracias nuevamente.
__________________
...y mañana caminaré por las calles pasando inadvertido, como siempre.

Última edición por mlara fecha: 24-08-2010 a las 01:32:49.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
No es un delirio, fue real o "virtual": Funeral virtual que se transforma en masacre! delphi.com.ar La Taberna 42 21-06-2007 18:00:59
MDI Virtual isg OOP 1 16-10-2006 11:18:37
Virtual Replay - Repetición Virtual de los Goles del Mundial delphi.com.ar La Taberna 0 26-06-2006 17:15:07
Virtual PC fjcg02 Linux 2 15-12-2004 18:11:18
Red virtual Pablo Carlos Varios 4 07-08-2004 02:24:31


La franja horaria es GMT +2. Ahora son las 07:18:23.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi