سؤال

دلفي (وربما الكثير من اللغات الأخرى) وقد فئة المساعدين.توفر هذه الطريقة لإضافة المزيد الأساليب القائمة فئة.دون فرعية.

لذا, ما هي استخدامات جيدة لفئة المساعدين?

هل كانت مفيدة؟

المحلول

أنا استخدامها:

  • إلى إدراج التعداد في 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

ورأيت منهم يستخدم لصنع أساليب الفئة المتاحة متناسقة عبر فصول: إضافة فتح / إغلاق وإظهار / إخفاء لجميع الطبقات من "نوع" نظرا بدلا من خصائص فقط نشطة وواضحة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top