Avatar billede hugopedersen Nybegynder
25. september 2011 - 12:01 Der er 16 kommentarer og
1 løsning

Kalde procedure ved hjælp af navn

Jeg har en række items på en combobox hvor jeg gerne vil kalde en bestemt procedure for hver. Altså hvis der står 'Kurt' så kaldes 'HanSkalHaveStorLøn' og hvis der står 'Gert' så kaldes 'HanSkalHaveLilleLøn' o.s.v.
Mit problem er at procedurerne ligger i en anden unit. Hvis de havde lagt på samme form som comboboxen, så kunne jeg have gået videre med en løsning som http://www.eksperten.dk/spm/946942#reply_7836526

Men det er ikke muligt for mig at flytte rutinerne da de også bruges af et andet program og så skal jeg pludseligt til at lave dobbelt vedligehold, og det dur ikke.

Jeg kunne selvfølgelig putte nogen funktioner ind i formen som bare kalder procedurerne i uniten, men det synes jeg heller ikke er så smart. At kalde en procedure hvis eneste formål er at kalde en anden er lidt noget gris synes jeg.
Avatar billede martinlind Nybegynder
25. september 2011 - 12:25 #1
Jeg ville ofre lidt tid på at lave det OOP :-)

Lav en Execute klasse som Kurt og Gert arver fra, så lægger du bare en instans af Kurt + Gert i Objects på combo'en og kører ExecuteKlasse.XXXX og så funker det :-)
Avatar billede hugopedersen Nybegynder
25. september 2011 - 16:03 #2
Den forstod jeg ikke - har du evt. et eksempel på hvordan det kan se ud?
Avatar billede martinlind Nybegynder
25. september 2011 - 19:47 #3
Type
  Moder = class
  public
    procedure Run; virtual;
  end;

  Kurt = class
  public
    procedure Run; override;
  end;

  Gert = class
  public
    procedure Run; override;
  end;


VAR
  Cnt : Integer;
  List : TStringlist;
Begin

  List := TStringlist.create;
  List.AddObject('Kurt',Kurt.Create);
  List.AddObject('Gert',Gert.Create);

  Moder(List.Objects[0]).Run; // kører Kurt
  Moder(List.Objects[1]).Run; // kører Gert
end;


Håber det hjælper lidt på vej :-)
Avatar billede hugopedersen Nybegynder
25. september 2011 - 19:53 #4
Måske - jeg skal lige se om ikke jeg kan få tid til at lave et forsøg i morgen hvis det er OK.
Avatar billede martinlind Nybegynder
25. september 2011 - 23:07 #5
Du er med på at jeg ikke har lavet alt koden ikk'

Du skal selv lave Kurt og Gert færdig, og så er det fuldstændig utestet :-)
Avatar billede hugopedersen Nybegynder
26. september 2011 - 09:38 #6
Jeg kan ikke få noget som helst fornuftigt ud af det her desværre
Avatar billede martinlind Nybegynder
26. september 2011 - 11:32 #7
Nå !
Det er ellers standart OOP og langt mere lige til end det link du har.

Har du lavet implementeringen af Kurt og Gert ?
Avatar billede a_nor Nybegynder
26. september 2011 - 13:23 #8
Hugo, du skal lige tilføje (moder) i typerne :

type
  Kurt = class (moder)
  public
    procedure Run; override;
  end;

  Gert = class (moder)
  public
    procedure Run; override;
  end;

Martin, tak for et fint lille eksempel
Avatar billede hugopedersen Nybegynder
26. september 2011 - 13:58 #9
Jeg fik det til syneladende til at fungere efter hensigten nu :-)

Mit testmodul ser nu sådan ud og jeg kan få det til at virke som det skal - tror jeg.

Og angående OOP, så er jeg ikke så meget inde i de dybere begreber i den verden. Jeg er nok også blevet for gammel til at lære det. Da jeg skrev mit første computerprogram var der kun sekventiel programudførelse muligt. Det var på en ZX 81.

unit U_ProcedureCall;

interface

{$M+}

type
  Moder = class
  public
    procedure Run(const aEmployer: string; const aDate: TDate); virtual;
  end;

  Kurt = class(Moder)
  public
    procedure Run(const aEmployer: string; const aDate: TDate); override;
  end;

  Gert = class(Moder)
  public
    procedure Run(const aEmployer: string; const aDate: TDate); override;
  end;

implementation

uses
  Dialogs, SysUtils;

procedure Moder.Run;
begin
end;

procedure Kurt.Run(const aEmployer: string; const aDate: TDate);
begin
  ShowMessage('Kører Kurt' + #13#10 +
              aEmployer + #13#10 +
              DatetimeToStr(aDate));
end;

procedure Gert.Run(const aEmployer: string; const aDate: TDate);
begin
  ShowMessage('Kører Gert' + #13#10 +
              aEmployer  + #13#10 +
              DatetimeToStr(aDate));
end;


end.
Avatar billede hugopedersen Nybegynder
26. september 2011 - 13:58 #10
Så jeg skal da lige have et svar så du kan få dine point.
Avatar billede martinlind Nybegynder
26. september 2011 - 14:12 #11
Smukt :-)

PS. Har lige set den nye Delphi, - 64 bit + mac + andriod + iphone osv. :-)
Avatar billede hugopedersen Nybegynder
26. september 2011 - 14:17 #12
OK - det må så være XE2 eller hvad?

(jeg er nu fint tilfreds med min XE med DevExpress på)
Avatar billede hugopedersen Nybegynder
26. september 2011 - 17:22 #13
Har dog opdaget at jeg ikke bare sådan lige kan flytte funktionen til mit projekt da jeg der har et rapportnavn som en streng på min Employer klasse (Employer.Report)  Den kan jeg ikke lige se hvordan jeg laver om. Men det kan nok gøres på en måde.
Avatar billede hugopedersen Nybegynder
27. september 2011 - 18:58 #14
Når jeg hiver data ud af den famøse combox så gør jeg det som her

EmployerData := cboEmployerData.Items.Objects[cboEmployerData.ItemIndex] as TEmployerData;

Min TEmployerData ser sådan her ud
type
  TEmployerData = class
  private
    fGUID: string;
    fName: string;
    fHeader: string;
    fReport: string;
  public
    property GUID: string read fGUID;
    property Name: string read fName;
    property Header: string read fHeader;
    property Report: string read fReport;
    constructor Create(const aGUID, aName, aHeader, aReport: string);
  end;
Avatar billede arne_v Ekspert
09. oktober 2011 - 05:01 #15
Det kan faktisk laves baade OO og proceduralt.

Eksempel:

program FPtr;

uses
  Classes, Contnrs;

Type
  P = class
  public
    procedure M; virtual; abstract;
  end;
  C1 = class(P)
  public
    procedure M; override;
  end;
  C2 = class(P)
  public
    procedure M; override;
  end;
  VFP = procedure;

procedure C1.M;

begin
  writeln('C1.M');
end;

procedure C2.M;

begin
  writeln('C2.M');
end;

procedure M1;

begin
  writeln('M1');
end;

procedure M2;

begin
  writeln('M2');
end;

var
  lst : TObjectList;
  pp : pointer;
  fa : array[0..1] of VFP;
  f : VFP;

begin
  (* The OO way *)
  lst := TObjectList.Create(true);
  lst.Add(C1.Create);
  lst.Add(C2.Create);
  for pp in lst do begin
    P(pp).M;
  end;
  lst.Free;
  (* The old way *)
  fa[0] := @M1;
  fa[1] := @M2;
  for f in fa do begin
    f;
  end;
end.
Avatar billede hugopedersen Nybegynder
09. oktober 2011 - 19:14 #16
arne_v ->

Din (* The old way *) løsning virker sålænge at man direkte skriver @M1. Mit 'problem' er at procedurenavnet ligger i en variabel og det vil den ikke acceptere at kalde.
Endvidere kan jeg ikke føre parametre med over i kaldet.
Det kan jeg så bare løse ved at hæfte nogle propertie på min Reports class og overføre dem den vej. Så det er det mindste problem.
Men det store issue er at jeg skal kalde en procedure som jeg har i en streng variabel.
Avatar billede arne_v Ekspert
09. oktober 2011 - 19:58 #17
Baade lookup by name og kald med parametre er mulige med den gammeldags maade.

Eksempel:

program FPtr21;

uses
  Classes, Contnrs, SysUtils;

Type
  P = class
  public
    procedure M(s : string); virtual; abstract;
  end;
  C1 = class(P)
  public
    procedure M(s : string); override;
  end;
  C2 = class(P)
  public
    procedure M(s : string); override;
  end;
  VFP = procedure(s : string);
  Key2VFP = record
    Key : string;
    F : VFP;
  end;

procedure C1.M(s : string);

begin
  writeln('C1.M : ' + s);
end;

procedure C2.M(s : string);

begin
  writeln('C2.M : ' + s);
end;

procedure M1(s : string);

begin
  writeln('M1 : ' + s);
end;

procedure M2(s : string);

begin
  writeln('M2 : ' + s);
end;

function MFind(a : array of Key2VFP; key : string) : Key2VFP;

label
  fin;

var
  res : Key2VFP;

begin
  for res in a do begin
    if res.Key = key then begin
      MFind := res;
      goto fin;
    end;
  end;
  raise Exception.Create('Ooops');
fin:
end;

var
  map : TFPHashObjectList; (* Lazaruz/FPC - use TObjectDictionary for Delphi *)
  fa : array[0..1] of Key2VFP;

begin
  (* The OO way *)
  map := TFPHashObjectList.Create(true);
  map.Add('#1', C1.Create);
  map.Add('#2', C2.Create);
  P(map.Find('#1')).M('foo');
  P(map.Find('#2')).M('bar');
  map.Free;
  (* The old way *)
  fa[0].Key := '#1';
  fa[0].F := @M1;
  fa[1].Key := '#2';
  fa[1].F := @M2;
  MFind(fa, '#1').F('foo');
  MFind(fa, '#2').F('bar');
end.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester