Was sind gute Einsatzmöglichkeiten für Klasse Helfer?
Frage
Delphi (und wahrscheinlich viele andere Sprachen) hat Klasse Helfer. Diese bieten eine Möglichkeit, fügen Sie zusätzliche Methoden zu einer vorhandenen Klasse. Ohne eine Unterklasse zu machen.
Also, was sind gute Einsatzmöglichkeiten für Klasse Helfer?
Lösung
Ich bin mit ihnen:
- VCL-Klassen verbessern.
-
Um Methoden zur TStrings Klasse hinzufügen, damit ich die gleichen Methoden in meine abgeleiteten Listen und in 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 }
-
Um den Zugriff auf Datensatzfelder und entfernen Gießen .
Andere Tipps
Zuerst war ich irgendwie skeptisch über Klassen Helfer. Aber dann las ich einen interessanten Blogeintrag und ich bin jetzt überzeugt, dass sie in der Tat nützlich sind.
Zum Beispiel, wenn Sie eine vorhandene Instanz Klasse zusätzliche Funktionalität wollen und aus irgendeinem Grund sind Sie nicht in der Lage die vorhandene Quelle zu ändern. Sie können eine Klasse Helfer erstellen, um diese Funktionalität hinzuzufügen.
Beispiel:
type
TStringsHelper = class helper for TStrings
public
function IsEmpty: Boolean;
end;
function TStringsHelper.IsEmpty: Boolean;
begin
Result := Count = 0;
end;
Jedes Mal wenn wir jetzt eine Instanz (eine Unterklasse) TStrings verwenden und TStringsHelper liegt im Rahmen. Wir haben Zugriff auf die Methode IsEmpty.
Beispiel:
procedure TForm1.Button1Click(Sender: TObject);
begin
if Memo1.Lines.IsEmpty then
Button1.Caption := 'Empty'
else
Button1.Caption := 'Filled';
end;
Weitere Informationen:
- Klasse Helfer können in einer separaten Einheit gespeichert werden, so dass Sie Ihre eigenen raffinierte Klasse Helfer hinzufügen können. Achten Sie darauf, diese Einheiten zu geben, einen einfachen Namen wie ClassesHelpers für Helfer für die Klassen Einheit zu erinnern.
- Es gibt auch Rekord Helfer.
- Wenn es mehr Klassen Helfer im Umfang, einige Probleme erwarten, nur ein Helfer verwendet werden kann.
Das klingt sehr ähnlich wie Erweiterungsmethoden in C # 3 (und VB9). Die beste Verwendung ich für sie gesehen haben, ist die Erweiterungen IEnumerable<T>
(und IQueryable<T>
), die gegen willkürliche Sequenzen LINQ Arbeit lässt:
var query = someOriginalSequence.Where(person => person.Age > 18)
.OrderBy(person => person.Name)
.Select(person => person.Job);
(oder was auch immer, natürlich). All dies ist machbar, weil Erweiterungsmethoden Sie erlauben effektiv zusammen zu verketten ruft zu statischen Methoden, die die gleiche Art nehmen, wie sie zurück.
Sie sind sehr nützlich für die Plug-In. Zum Beispiel, sagen wir, einem Projekt eine bestimmte Datenstruktur definiert und es wird auf eine Disc in einer bestimmten Art und Weise gespeichert. Aber dann ein anderes Programm tut etwas sehr ähnlich, aber die Datendatei ist anders. Aber Sie wollen nicht Ihre EXE mit einem Bündel von Import-Code für eine Funktion aufblasen, dass viele Benutzer nicht verwenden müssen. Sie können ein Plugin-Framework verwenden und Importeure in ein Plugin setzen, die wie folgt funktionieren würde:
type
TCompetitionToMyClass = class helper for TMyClass
public
constructor Convert(base: TCompetition);
end;
Und dann den Konverter definieren. Eine Einschränkung: eine Klasse Helfer ist keine Klasse Freund . Diese Technik funktioniert nur, wenn es möglich ist, komplett aufgebaut, um ein neues TMyClass Objekt durch seine öffentlichen Methoden und Eigenschaften. Aber wenn Sie können, es funktioniert wirklich gut.
Das erste Mal, dass ich erinnere mich, zu erfahren, was Sie „Klasse Helfer“ sind Aufruf war beim Lernen Objective C. Kakao (Apples Objective C-Framework) verwendet, was genannt wird „Kategorien“.
Eine Kategorie können Sie eine vorhandene Klasse erweitern durch Hinzufügen Sie besitzen Methoden ohne Subclassing. In der Tat Cocoa fordert Sie dazu auf Subclassing wenn möglich zu vermeiden. Oft ist es sinnvoll zu Unterklasse, aber oft kann es mit Kategorien vermieden werden.
Ein gutes Beispiel für die Verwendung einer Kategorie in Cocoa ist das, was "Key Value-Code (KVC)" und nennt "Key Value Observing (KVO)."
Dieses System wird unter Verwendung implementiert zwei Kategorien (NSKeyValueCoding und NSKeyValueObserving). Diese Kategorien definieren und Methoden implementieren, die zu jeder Klasse hinzugefügt werden können, die Sie wollen. Zum Beispiel Kakao fügt hinzu: „Konformität“ zu KVC / KVO durch diese Kategorien unter Verwendung von Methoden zu NSArray hinzufügen wie:
- (id)valueForKey:(NSString *)key
NSArray Klasse hat weder eine Erklärung noch eine Implementierung dieser Methode. Jedoch durch die Verwendung der Kategorie. Sie können dieses Verfahren auf jedem NSArray Klasse aufrufen. Sie sind nicht zu gewinnen KVC / KVO Konformität erforderlich NSArray Unterklasse.
NSArray *myArray = [NSArray array]; // Make a new empty array
id myValue = [myArray valueForKey:@"name"]; // Call a method defined in the category
Mit dieser Technik ist es einfach KVC / KVO Unterstützung für Ihre eigenen Klassen hinzuzufügen. Java-Schnittstellen erlauben Sie Methodendeklarationen hinzuzufügen, aber Kategorien können Sie auch die tatsächlichen Implementierungen zu bestehenden Klassen hinzuzufügen.
Wie Gamecat zeigt, ist TStrings ein guter Kandidat Tipparbeit zu vermeiden:
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;
Haben Sie jemals brauchen mehrzeilige Zeichenfolgen in der Registrierung zuzugreifen?
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;
Ich würde nicht empfehlen, sie zu benutzen, da lese ich diesen Kommentar:
"Das größte Problem mit Klasse Helfer aus dem p.o.v der mit ihnen in Ihren eigenen Anwendungen, ist die Tatsache, dass nur eine Klasse Helfer für einen bestimmten Klasse kann jederzeit in ihrem Umfang sein.“ ... „Das heißt, wenn Sie zwei Helfer haben in Umfang, wird nur eine zu erkennen durch den Compiler. Sie werden nicht bekommen jede Warnungen oder auch Hinweise zu allen anderen Helfer, die versteckt werden können. "
http://davidglassborow.blogspot.com /2006/05/class-helpers-good-or-bad.html
Ich habe sie für die Bereitstellung von Klassenmethoden konsistent über Klassen gesehen: Hinzufügen Öffnen / Schließen und Show / Hide für alle Klassen eines bestimmten „Typ“ und nicht nur aktive und sichtbare Eigenschaften.