Jak ustawić wartość domyślną pola w strukturze?

0

Witam.

Mam pytanie czy ktoś ma pomysły jak ustawić wartość domyślną w rekordzie?
dla przykładu zasada działania mogła by być taka:

type
  TDane = record
    Licznik: Integer = 100;
    nazwa: String;
  end;

var
  Licznik: Integer = 100;

Bezpośrednio w zmiennej to działa a w rekordzie nie, więc szukam sposobu.
Pozdrawiam

2

Przecież TDane to deklaracja typu rekordowego więc jak chcesz przypisać wartość ale w zmiennej tego typu jak najbardziej można:

var Dane: TDane = (Licznik: 100; nazwa: 'test');
0

O dzięki, jest to sposób na to ale gdyby się dało bezpośrednio przy deklaracji odpadło by trochę kodu, ponieważ potem taki rekord może być array of TDane i dla tego szukam sposobu na to.

2

Jeżeli tablica jest statyczna (czyli od początku ma określoną wielość) to można:

var  Dane: array [0..1] of TDane = ((Licznik: 100; nazwa: 'test'),
                                (Licznik: 1000; nazwa: 'test2'));

ale przy tablicach dynamicznych nie da się.

0

Dziękuję, zawsze to jakieś udogodnienie.
Zapewne by trzeba coś z pamięcią i obsługa danych pomieszać.. ale wtedy to już prościej w procedurze Create wrzucić przypisanie.

4
Integers napisał(a)

ale gdyby się dało bezpośrednio przy deklaracji

Ale to nie jest możliwe w takiej postaci, w jaki podałeś z prostej przyczyny - deklarujesz typ rekordowy, nie stałą rekordową; W takiej postaci określasz tylko pola i ich typy;

Idealnego rozwiązania nie widzę, ale możesz skorzystać z advanced records i dodać do typu struktury procedurę, w której zainicjujesz wartości pól, np:

type
  TData = record
    Counter: Integer;
    Name: String;
    procedure InitFields();
    procedure ShowFields();
  end;

  procedure TData.InitFields();
  begin
    Counter := 100;
    Name := 'Foo';
  end;

  procedure TData.ShowFields();
  begin
    WriteLn(Counter, ': ', Name);
  end;

przykład użycia:

var
  Data: TData;
begin
  Data.InitFields();
  Data.ShowFields();
  ReadLn;
end.

jak widać na początku wywołujemy procedurę wypełniającą pola struktury, następnie wyświetlamy je w oknie konsoli; Na wyjściu zobaczymy:

100: Foo
Taka możliwość istnieje w Delphi od jakiegoś czasu, a w Lazarusie trzeba skorzystać z dyrektywy {$MODESWITCH ADVANCEDRECORDS}, aby można było użyć takiej konstrukcji;

Więcej informacji znajdziesz w dokumentacji: http://docwiki.embarcadero.com/RADStudio/XE5/en/Structured_Types

0

Jak to zobaczyłem to nie byłem Pewny ale na Delphi 2007 działa. Super dzięki.

edit:

@Furious Programming mam jeszcze pytanie czy wiesz może jak to jest z zajętością pamięci przez te funkcje podpięte pod dany rekord? np w przykładzie, który pokazałeś? Jeśli np zdeklaruję tabelę statyczna lub dynamiczna powiedzmy 1000 pozycji to każdy rekord będzie w pamięci miał tylko wywołanie procedury a ciało procedur kompilator w kodzie zamieści tylko raz?
Nie sadzę zęby koder zrobił to tak aby kod procedury był powielany tyle razy ile jest pozycji w tablicy .. ale chcę się upewnić.

0

Nie sądzę aby dla każdego tworzonego rekordu była alokowana pamięć dla pól a także jego metod (jako kodu, nie wskaźników na metody) - to by sensu nie miało; Działa to pewnie na takiej samej zasadzie jak w przypadku klas, ale źródła do poczytania w tym momencie nie mogę podać; Spróbuj sobie poszukać na ten temat informacji w sieci.

2

wiesz może jak to jest z zajętością pamięci przez te funkcje podpięte pod dany rekord?

Funkcje nie są częścią pamięci rekordu (w przypadku klas mielibyśmy VMT, które nota bene zajmuje te swoje bajty, ale nie, gdy mowa o rekordach) - równie dobrze mógłbyś stworzyć po prostu osobną funkcję:

Procedure InitFields(var Data: TData);
Begin
 Data. ...
End;

I wyszłoby na jedno (w advanced records masz robione coś takiego, tyle że niejawnie).

Jeśli np zdeklaruję tabelę statyczna lub dynamiczna powiedzmy 1000 pozycji to każdy rekord będzie w pamięci miał tylko wywołanie procedury a ciało procedur kompilator w kodzie zamieści tylko raz?

Jaki byłby sens deklarowania takich funkcji 1000 razy? I gdzie miałyby być tworzone? W jaki sposób?

0

No to super, dzięki. Po prostu miałem wątpliwości co do oszczędności KB RAMu

To jeszcze taka wątpliwość/ pytanie nasuwające się po przeanalizowaniu Waszych wypowiedzi: że (jeśli dobrze mi się wydaje) prostszy w użyciu byłby taki rekord z zadeklarowanymi procedurami i funkcjami bo nie trzeba wywoływać Create jak w przypadku klasy ale z kolei klasa z samej definicji może po wykorzystaniu jej zwolnić miejsce po wywołaniu klasa.Destroy...
W takim razie czy oprócz możliwości destroy jest coś co przemawia za wyższością metody rekordu czy klasy?
Co się bardziej opłaca używać? o ile są jakieś znaczące różnice.

Może podam przykład, że chodzi mi o jakąś grupę/ record danych dość rozbudowaną, które są w programie używane od startu do jego zamknięcia, wiec nie zależy mi na Destroy.

0

W takim razie czy oprócz możliwości destroy jest coś co przemawia za wyższością metody rekordu czy klasy?

Dziedziczenie, hermetyzacja, polimorfizm, typy generyczne... nic z tego nie istnieje w rekordach.

0

Fakt, dzięki

2
Integers napisał(a)

prostszy w użyciu byłby taki rekord z zadeklarowanymi procedurami i funkcjami bo nie trzeba wywoływać Create jak w przypadku klasy ale z kolei klasa z samej definicji może po wykorzystaniu jej zwolnić miejsce po wywołaniu klasa.Destroy...

A jak chcesz korzystać z tych rekordów - lokalnie (za pomocą zmiennych) czy tworząc je dynamicznie trzymając referencję we wskaźniku? Bo jeśli to drugie, to i tak będziesz musiał alokować pamięć przez np. GetMem i zwalniać przez FreeMem; Jeśli chodzi o klasy to wystarczy wywołać konstruktor a zwolnić metodą Free (a nie bezpośrednio przez Destroy); Wszystko zależy od tego co chcesz z nich budować i jak chcesz zarządzać pamięcią; Jak koniecznie chcesz zaoszczędzić te kilka kilobajtów to użyj struktur, a jeśli chcesz większej wygody i przede wszystkim większych możliwości (np. dziedziczenia) to skorzystaj z klas;

Integers napisał(a)

Co się bardziej opłaca używać? o ile są jakieś znaczące różnice.

To zależy od przypadku, bo do jednych celów bardziej odpowiednie są rekordy, a do innych klasy; Różnica jest znacząca (patrz post @Patryk27); Dopóki nie napiszesz do czego chcesz je wykorzystać to dobrej odpowiedzi nie dostaniesz; Bo to:

Integers napisał(a)

Może podam przykład, że chodzi mi o jakąś grupę/ record danych dość rozbudowaną, które są w programie używane od startu do jego zamknięcia, wiec nie zależy mi na Destroy.

to nie jest przykład - można go interpretować na wiele sposobów, czyli dalej nic nie wiadomo.

0

Dziękuje Wam za objasnienia. Nie chodzi o jeden konkretny przypadek więc takie streszczenie jest całkiem na miejscu. Bardziej to było luźne pytanie niż jakiś konkretny problem. Po prostu z programu na program w grę wchodzą coraz większe struktury danych. Niektóre zmienne, klasy, moduły przechodzą do nowych programów więc zastanawiam się jak to uporządkować a jeśli już robić porządki to żeby to miało ręce i nogi.

1

To też w sumie dość ogólnie opisałeś - żeby cokolwiek mądrze doradzić trzeba by dokładnie wiedzieć co chcesz zrobić, jak to coś wykorzystać i jak chcesz zoptymalizować kod;

Optymalizacja nie zawsze ma sens, bo jeśli zysk wynosi kilka procent to niezbyt się opłaca, jeśli po optymalizacji kod jest dłuższy i mniej czytelny; Wszystko i tak zależy od tego ile czasu oszczędzi te kilka procent - czy kilka milisekund, czy kilka minut/godzin.

0

Racja :)

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