ما هي استخدامات جيدة لفئة المساعدين?
سؤال
دلفي (وربما الكثير من اللغات الأخرى) وقد فئة المساعدين.توفر هذه الطريقة لإضافة المزيد الأساليب القائمة فئة.دون فرعية.
لذا, ما هي استخدامات جيدة لفئة المساعدين?
المحلول
أنا استخدامها:
- إلى إدراج التعداد في VCL الفئات التي لا تنفذها.
- إلى تعزيز VCL الطبقات.
لإضافة طرق إلى TStrings الدرجة حتى أتمكن من استخدام نفس الأساليب في بلدي مشتقة قوائم و في 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 }
لتبسيط الوصول إلى حقول السجل ، إزالة صب.
نصائح أخرى
في البداية كنت نوع من المشككين عن فئة المساعدين.ولكن بعد ذلك قرأت مثيرة للاهتمام بلوق الدخول و الآن أنا مقتنع أنهم في الواقع مفيدة.
على سبيل المثال, إذا كنت تريد وظيفة اضافية موجودة سبيل المثال فئة لسبب ما لم تكن قادرا على تغيير القائمة المصدر.يمكنك إنشاء فئة المساعد لإضافة هذه الوظيفة.
على سبيل المثال:
type
TStringsHelper = class helper for TStrings
public
function IsEmpty: Boolean;
end;
function TStringsHelper.IsEmpty: Boolean;
begin
Result := Count = 0;
end;
في كل مرة, نحن الآن استخدام مثيل (فئة فرعية من) TStrings ، TStringsHelper ضمن نطاق.لدينا إمكانية الوصول إلى طريقة IsEmpty.
على سبيل المثال:
procedure TForm1.Button1Click(Sender: TObject);
begin
if Memo1.Lines.IsEmpty then
Button1.Caption := 'Empty'
else
Button1.Caption := 'Filled';
end;
ملاحظات:
- فئة المساعدين يمكن تخزينها في وحدة منفصلة بحيث يمكنك إضافة الخاصة بك أنيق فئة المساعدين.تأكد من إعطاء هذه الوحدات من السهل أن نتذكر اسم مثل ClassesHelpers على المساعدين على دروس الوحدة.
- وهناك أيضا تسجيل المساعدين.
- إذا كان هناك عدة فئة المساعدين داخل نطاق تتوقع بعض المشاكل واحدة فقط المساعد يمكن استخدامها.
وهذا يشبه كثيرا ما طرق الإرشاد في C # 3 (وVB9). أفضل استخدام رأيت بالنسبة لهم هو التمديد لIEnumerable<T>
(وIQueryable<T>
) الذي يتيح العمل LINQ ضد تسلسل التعسفية:
var query = someOriginalSequence.Where(person => person.Age > 18)
.OrderBy(person => person.Name)
.Select(person => person.Job);
و(أو أيا كان، بالطبع). كل هذا غير قابلة للتنفيذ لطرق الإرشاد تسمح لك على سلسلة معا بشكل فعال يدعو إلى أساليب ثابتة والتي تأخذ نفس نوع عودتهم.
وانهم مفيدة للغاية بالنسبة المكونات الإضافية. فعلى سبيل المثال، دعنا نقول يحدد المشروع بنية بيانات معينة وانها حفظها إلى القرص بطريقة معينة. ولكن بعد ذلك بعض البرامج الأخرى لا شيء مشابه جدا، لكن ملف البيانات ومختلفة. ولكنك لا تريد أن تشعر بالانتفاخ EXE الخاص بك مع مجموعة من التعليمات البرمجية الاستيراد لميزة أن الكثير من المستخدمين لن تحتاج إلى استخدام. يمكنك استخدام إطار البرنامج المساعد ووضع المستوردين إلى البرنامج المساعد الذي سيعمل مثل هذا:
type
TCompetitionToMyClass = class helper for TMyClass
public
constructor Convert(base: TCompetition);
end;
وثم تحديد المحول. التحذير واحدة: فئة <م> المساعد م> ليس فئة <م> صديق م>. وهذه التقنية تعمل فقط إذا كان من الممكن تماما الإعداد كائن TMyClass جديد من خلال الأساليب والخصائص العامة. ولكن إذا كنت تستطيع، وأنها تعمل بشكل جيد.
وكانت المرة الأولى أتذكر تعاني ما كنت داعيا "المساعدين من الدرجة" كان الهدف في الوقت الذي تعلم C. الكاكاو (إطار أبل C الهدف) يستخدم ما يسمى "فئات".
وهناك فئة يسمح لك على توجيه الطبقة الحالية بإضافة كنت تملك أساليب دون شاء subclasses ترث. في الواقع الكاكاو تشجعك على تجنب شاء subclasses ترث عندما يكون ذلك ممكنا. في كثير من الأحيان أنه من المنطقي أن فئة فرعية، ولكن غالبا ما يمكن تجنبها باستخدام فئات.
وخير مثال على استخدام فئة في الكاكاو هو ما يسمى "مفتاح كود القيمة (KVC)" و "قيمة مفتاح مراقبة (المنظمة من)".
ويتم تنفيذ هذا النظام باستخدام فئتين (NSKeyValueCoding وNSKeyValueObserving). هذه الفئات على تحديد وتنفيذ الأساليب التي يمكن أن تضاف إلى أي فئة تريد. على سبيل المثال يضيف الكاكاو "التوافق" لKVC / المنظمة من خلال استخدام هذه الفئات لإضافة أساليب لNSArray مثل:
- (id)valueForKey:(NSString *)key
وليس لديها الطبقة NSArray إما إعلانا ولا على تنفيذ هذا الأسلوب. ومع ذلك، من خلال استخدام هذه الفئة. يمكنك استدعاء هذا الأسلوب على أي فئة NSArray. أنك لست في حاجة إلى فئة فرعية NSArray للحصول على KVC / المنظمة من التوافق.
NSArray *myArray = [NSArray array]; // Make a new empty array
id myValue = [myArray valueForKey:@"name"]; // Call a method defined in the category
وباستخدام هذه التقنية يجعل من السهل لإضافة دعم KVC / المنظمة من أن الطبقات الخاصة بك. واجهات جافا تسمح لك لإضافة إعلانات طريقة، ولكن فئات تسمح لك أيضا إضافة تطبيقات الفعلية إلى الفئات الموجودة.
وكما يبين GameCat، TStrings هو مرشح جيد لتجنب بعض النسخ:
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;
هل كانت هناك حاجة من أي وقت مضى للوصول إلى سلاسل خط متعددة في التسجيل؟
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;
وأنا لا أوصي استخدامها، منذ قرأت هذا التعليق:
<اقتباس فقرة>و"إن أكبر مشكلة مع الطبقة المساعدين، من p.o.v من استخدامها في التطبيقات الخاصة بك، هو حقيقة أن واحدة فقط المساعد فئة معين قد تكون فئة في نطاق في أي وقت ". ... "وهذا هو، إذا كان لديك اثنين من المساعدين في نطاق، سيتم الاعتراف بها واحدة فقط بواسطة المترجم. أنت لن تحصل أي تحذيرات أو حتى تلميحات حول أي شيء آخر المساعدين التي قد تكون مخفية ".
اقتباس فقرة>http://davidglassborow.blogspot.com /2006/05/class-helpers-good-or-bad.html
ورأيت منهم يستخدم لصنع أساليب الفئة المتاحة متناسقة عبر فصول: إضافة فتح / إغلاق وإظهار / إخفاء لجميع الطبقات من "نوع" نظرا بدلا من خصائص فقط نشطة وواضحة.