25. september 2011 - 12:01Der 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.
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 :-)
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;
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.
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.
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.
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.
Synes godt om
Ny brugerNybegynder
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.