Jakie są dobre zastosowania dla pomocników klasowych?
Delphi (i prawdopodobnie wiele innych języków) posiada helpery klas. Zapewniają one możliwość dodania dodatkowych metod do istniejącej klasy. Bez tworzenia podklasy.
Więc, jakie są dobre zastosowania dla pomocników klasowych?
8 answers
Używam ich:
- do Wstaw enumeratory do klas VCL, które ich nie implementują.
- do wzmocnij klasy VCL.
-
Aby dodać metody do klasy TStrings, abym mógł używać tych samych metod w moich listach pochodnych i w TStringList.
TGpStringListHelper = class helper for TStringList public function Last: string; function Contains(const s: string): boolean; function FetchObject(const s: string): TObject; procedure Sort; procedure Remove(const s: string); end; { TGpStringListHelper }
Aby uprościć dostęp do pól rekordów i usunąć casting .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 13:44:29
Na początku byłem trochę sceptyczny w stosunku do pomocników klasowych. Ale potem przeczytałem ciekawy wpis na blogu i teraz jestem przekonany, że są rzeczywiście przydatne.
Na przykład, jeśli potrzebujesz dodatkowej funkcjonalności dla istniejącej klasy instancji i z jakiegoś powodu nie możesz zmienić istniejącego źródła. Możesz utworzyć pomocnika klasy, aby dodać tę funkcjonalność.
Przykład:
type
TStringsHelper = class helper for TStrings
public
function IsEmpty: Boolean;
end;
function TStringsHelper.IsEmpty: Boolean;
begin
Result := Count = 0;
end;
Za każdym razem używamy instancji (podklasy) TStrings i TStringsHelper jest w zasięgu. Mamy dostęp do metody IsEmpty.
Przykład:
procedure TForm1.Button1Click(Sender: TObject);
begin
if Memo1.Lines.IsEmpty then
Button1.Caption := 'Empty'
else
Button1.Caption := 'Filled';
end;
Uwagi:
- pomocniki klas mogą być przechowywane w osobnej jednostce, więc możesz dodać własne sprytne pomocniki klas. Pamiętaj, aby nadać tym jednostkom łatwą do zapamiętania nazwę, taką jak ClassesHelpers dla pomocników dla jednostki Classes.
- istnieją również pomocnicy rekordów.
- jeśli w zasięgu jest wiele pomocników klas, spodziewaj się pewnych problemów, tylko jednego można użyć pomocnika.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-05 13:51:33
To brzmi bardzo podobnie do metod rozszerzeń w C # 3 (i VB9). Najlepsze zastosowanie jakie widziałem dla nich to rozszerzenia IEnumerable<T>
(i IQueryable<T>
), które pozwalają LINQ pracować z dowolnymi sekwencjami:
var query = someOriginalSequence.Where(person => person.Age > 18)
.OrderBy(person => person.Name)
.Select(person => person.Job);
(lub cokolwiek, oczywiście). Wszystko to jest wykonalne, ponieważ metody rozszerzeń pozwalają efektywnie łączyć wywołania do metod statycznych, które przyjmują ten sam typ, co zwracane.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 13:18:30
Są bardzo przydatne dla wtyczek. Załóżmy na przykład, że twój projekt definiuje pewną strukturę danych i jest zapisywany na dysku w określony sposób. Ale inny program robi coś bardzo podobnego, ale plik danych jest inny. Ale nie chcesz nadmuchać EXE z kilkoma kodami importu dla funkcji, której wielu użytkowników nie będzie musiało używać. Możesz użyć frameworka wtyczki i umieścić go w wtyczce, która działałaby tak:
type
TCompetitionToMyClass = class helper for TMyClass
public
constructor Convert(base: TCompetition);
end;
A następnie zdefiniuj konwerter. Jedno zastrzeżenie: klasa helper nie jest klasą friend. Ta technika zadziała tylko wtedy, gdy możliwe jest całkowite skonfigurowanie nowego obiektu TMyClass za pomocą jego publicznych metod i właściwości. Ale jeśli możesz, to działa naprawdę dobrze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 20:37:49
Pierwszy raz pamiętam, że doświadczyłem tego, co nazywacie "pomocnikami klas" , podczas nauki Objective C. Cocoa (Framework Objective C firmy Apple) używa tak zwanych "kategorii"."
Kategoria pozwala na rozszerzenie istniejącej klasy poprzez dodanie własnych metod bez podklasowania. W rzeczywistości Cocoa zachęca do unikania podklasowania, gdy to możliwe. Często podklasa ma sens, ale często można jej uniknąć za pomocą kategorii.
Dobry przykład użycia kategorii w Cocoa to tzw. " Key Value Code (KVC)" i " Key Value Observing (KVO)."
Ten system jest zaimplementowany przy użyciu dwóch kategorii (NSKeyValueCoding i NSKeyValueObserving). Te kategorie definiują i implementują metody, które można dodać do dowolnej klasy. Na przykład Cocoa dodaje "zgodność" do KVC/KVO, używając tych kategorii, aby dodać metody do NSArray, takie jak:
- (id)valueForKey:(NSString *)key
Klasa NSArray nie posiada ani deklaracji, ani implementacji tej metody. Jednakże, poprzez użycie kategorii. Możesz wywołać tę metodę na dowolnej klasie NSArray. Nie musisz podklasować NSArray, aby uzyskać zgodność z KVC/KVO.
NSArray *myArray = [NSArray array]; // Make a new empty array
id myValue = [myArray valueForKey:@"name"]; // Call a method defined in the category
Użycie tej techniki ułatwia dodanie obsługi KVC/KVO do własnych klas. Interfejsy Java pozwalają dodawać deklaracje metod, ale kategorie pozwalają również dodawać rzeczywiste implementacje do istniejących klas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 14:10:26
Jak pokazuje GameCat, TStrings jest dobrym kandydatem, aby uniknąć typowania:
type
TMyObject = class
public
procedure DoSomething;
end;
TMyObjectStringsHelper = class helper for TStrings
private
function GetMyObject(const Name: string): TMyObject;
procedure SetMyObject(const Name: string; const Value: TMyObject);
public
property MyObject[const Name: string]: TMyObject read GetMyObject write SetMyObject; default;
end;
function TMyObjectStringsHelper.GetMyObject(const Name: string): TMyObject;
var
idx: Integer;
begin
idx := IndexOf(Name);
if idx < 0 then
result := nil
else
result := Objects[idx] as TMyObject;
end;
procedure TMyObjectStringsHelper.SetMyObject(const Name: string; const Value:
TMyObject);
var
idx: Integer;
begin
idx := IndexOf(Name);
if idx < 0 then
AddObject(Name, Value)
else
Objects[idx] := Value;
end;
var
lst: TStrings;
begin
...
lst['MyName'] := TMyObject.Create;
...
lst['MyName'].DoSomething;
...
end;
Czy kiedykolwiek potrzebowałeś dostępu do ciągów wielowierszowych w rejestrze?
type
TRegistryHelper = class helper for TRegistry
public
function ReadStrings(const ValueName: string): TStringDynArray;
end;
function TRegistryHelper.ReadStrings(const ValueName: string): TStringDynArray;
var
DataType: DWord;
DataSize: DWord;
Buf: PChar;
P: PChar;
Len: Integer;
I: Integer;
begin
result := nil;
if RegQueryValueEx(CurrentKey, PChar(ValueName), nil, @DataType, nil, @DataSize) = ERROR_SUCCESS then begin
if DataType = REG_MULTI_SZ then begin
GetMem(Buf, DataSize + 2);
try
if RegQueryValueEx(CurrentKey, PChar(ValueName), nil, @DataType, PByte(Buf), @DataSize) = ERROR_SUCCESS then begin
for I := 0 to 1 do begin
if Buf[DataSize - 2] <> #0 then begin
Buf[DataSize] := #0;
Inc(DataSize);
end;
end;
Len := 0;
for I := 0 to DataSize - 1 do
if Buf[I] = #0 then
Inc(Len);
Dec(Len);
if Len > 0 then begin
SetLength(result, Len);
P := Buf;
for I := 0 to Len - 1 do begin
result[I] := StrPas(P);
Inc(P, Length(P) + 1);
end;
end;
end;
finally
FreeMem(Buf, DataSize);
end;
end;
end;
end;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 14:27:36
Nie polecam ich używać, ponieważ przeczytałem ten komentarz:
" największy problem z klasą pomocnicy, od P. O. v z ich używania w swoich własnych aplikacjach, jest fakt że tylko jeden Pomocnik klasy dla danego klasa może być w zasięgu w każdej chwili." ... "To znaczy, jeśli masz dwóch pomocników w zakresie, tylko jeden zostanie uznany przez kompilator. Nie dostaniesz żadnych ostrzeżenia lub nawet podpowiedzi o innych pomocnicy, którzy mogą być Ukryty."
Http://davidglassborow.blogspot.com/2006/05/class-helpers-good-or-bad.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-04 05:57:25
Widziałem je używane do udostępniania dostępnych metod klas spójnych między klasami: dodawanie Open / Close I Show / Hide do wszystkich klas danego "typu", a nie tylko aktywnych i widocznych właściwości.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-27 11:32:59