Właściwość typu TClass i SetValue - najlepsza opcja

0

Tak się zastanawiam czy sposób w jaki do tej pory operowałem na takich "zmiennych" jest właściwy. Przedstawiam fragment kodu na którym wyjaśnię wszystko:

TKlasa = class
  private
     fIdHttp: TIdHttp;
  public
     property Connection: TIdHttp read fidHttp write fIdHttp;
     procedure Test;
end;

procedure TKlasa.Test;
begin
   //try   <- sekcje z try pomijam zawsze gdyż zwalniam globalnie np. przy wyłączeniu programu
      fIdHttp.Get('coś tam');
   //finally //except
   //    fIdHttp.Free;
   //end;
end;

Takie przypisywanie to operowanie na wskaźnikach czyli odnoszę się zawsze np. w tym przypadku do IdHttp które przypisuje

Klasa.Connection := Form1.IdHttp1;

I tak się zastanawiam czy to jest właściwe czy czasem nie powinienem tworzyć kopii lustrzanej danej klasy, tutaj TIdHttp?

1

Wszystko zależy od przeznaczenia. W większości przypadków gdy potrzebuję upublicznić pole klasy będące referencją, to tworzę właściwość read-only, po to aby nie dało się nadpisać referencji. W Twoim przypadku pole raczej nie powinno istnieć, a instancję TIdHttp powinieneś przekazać w parametrze metody Test. Według mnie będzie to logiczne.

Przy okazji – jeśli masz na myśli instancję klasy to pisz że chodzi o referencję. Wiadomo że referencje wewnętrznie są niczym innym jak wskaźnikami, jednak wskaźniki to osobne elementy języka i zamienne używanie tego terminu może wprowadzać w błąd czytających.

0

Czy przypadkiem nie próbujesz wyważyć otwartych drzwi i stworzyć singletona?

0

@furious programming

instancję TIdHttp powinieneś przekazać w parametrze metody Test. Według mnie będzie to logiczne.

Jeżeli referencję potrzebuje tylko w jednej procedurze to ok. Ale chodzi mi o rozwiązanie gdzie wiele procedur w danej klasie wymaga dostępu do tej referencji wtedy chyba najlepiej użyć zmiennej globalnej w danej klasie.

@_13th_Dragon,

Czy przypadkiem nie próbujesz wyważyć otwartych drzwi i stworzyć singletona?

No masz troszkę racji. Ale nie umiem inaczej. np wątki. Mam formę główną, na której mam komponent TUniConnection czy cokolwiek innego nawet TIdHttp. Teraz mam drugą formę o nazwie ModulObslugi z kilkoma komponentami TGauge. Procedury z tej formy uruchamiają wątek. I teraz jak przekazać komponent z głównej formy do wątku aby ten mógł się połączyć z serwerem, ponadto do wątku muszę jeszcze przekazać zmienną aby mógł się odnieść do komponentów TGauge.

Jedyne co mi przychodzi to kolejne przekazywanie przez zmienne referencji obiektu TUniConnection czy TForm;

0
  1. Constructor w ModulObslugi prywatny

class procedure ModulObslugi.Execute(parametry):ModulObslugi;
begin
Result:=Create(Application);
Result.SetParameters(parametry);
Result.Show;
end;

1. Do ModulObslugi przez Execute przekaż metodę z formy głównej która potrafi poprawnie zainicjować TUniConnection/TIdHttp oraz metodę która może operować na Gauge
0

Czyli tak to mam zrobić w przypadku wątków?

type
  TProcessTime = class(TThread)
  private
    fObject: TObject;
    fWork: integer;
    procedure ShowTime;
  public
    constructor Create;
    class procedure Execute(ALabel: TObject):TProcessTime ;
    property SetParameters : TObject read fObject write fObject;
  protected
    procedure Execute; override;
  end;

constructor TProcessTime.Create;
begin
  fWork := 0;
  FreeOnTerminate := True;
  inherited Create(true);
end;

procedure TProcessTime.ShowTime;
begin
  if fObject is TLabel then
     TLabel(fObject).Caption := 'Czas trwania: ' + IntToTime(fWork);
end;

procedure TProcessTime.Execute;
var
  I: integer;
begin
  while not Terminated do
  begin
    for I := 0 to 99 do
    begin
      if not CloseForm then
        if I = 0 then
          Synchronize(ShowTime)
        else
      else
        Terminate;
      sleep(10);
    end;
    Inc(fWork);
  end;
end;

class procedure TProcessTime .Execute(ALabel: TObject):TProcessTime ;
begin
  Result:=Create(Application);
  Result.SetParameters := ALabel;
  Result.Resume;
end;
0

Co chcesz osiągnąć? Zegar na formatce? Do tego nie potrzebujesz wątku.
Oblicz czas do najbliższej pełną sekundy: x:=1000-(Trunc(Now()*SecsPerDay*1000))mod(1000);
Weź nie więcej niż 50 ms x:=Min(x,50);
Ustaw timer: SetTimer(Handle,1,x);
Złap zdarzenie w: procedure Form1.WmTimer(var Msg:TWmTimer);message WM_TIMER; message WM_TIMER;- tylko w deklaracji
No i wewnątrz zabij timer: KillTimer(Handle,Msg.TimerId); wyświetl czas i znowu nastaw timer jak wyżej.

0

@Rafał D: a co w ogóle chcesz osiągnąć? Do czego konkretnie to ma służyć?

1 użytkowników online, w tym zalogowanych: 0, gości: 1