سؤال

Delphi 2009 ، من بين بعض الأشياء الرائعة ، لديها أيضًا أساليب مجهولة. لقد رأيت الأمثلة ، ونشرات المدونة المتعلقة بالأساليب المجهولة ، لكنني لم أحصل عليها بعد. هل يمكن لأحد أن يشرح لماذا يجب أن أكون متحمسًا؟

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

المحلول

فقط فكر في رمز رد الاتصال النموذجي حيث تحتاج إلى توفير بيانات للاستدعاء. غالبًا ما تكون هذه البيانات مطلوبة لرد الاتصال فقط, ، ومع ذلك ، عليك القفز عبر عدد من الأطواق للحصول عليها دون الحاجة إلى الاستقالة لممارسات غير صديقة مثل المتغيرات العالمية. من خلال الطرق المجهولة ، يمكن للبيانات البقاء في مكانها - ليس عليك أن تمد نطاقها بشكل غير ضروري أو نسخها إلى بعض الكائنات المساعد. ما عليك سوى كتابة رمز رد الاتصال الخاص بك في مكانه كطريقة مجهولة ، ويمكنه الوصول بالكامل إلى جميع المتغيرات المحلية ومعالجتها في الموقع حيث يتم تعريف الطريقة المجهولة (وليس حيث يطلق عليها!).

هناك جوانب أخرى من الأساليب المجهولة ، بوضوح حقيقة أنها ، حسناً: مجهول ، لكن هذا هو الجهاز الذي جعلهم حقًا "انقر" بالنسبة لي ...

نصائح أخرى

يرجى إلقاء نظرة على الإغلاق.

دلفي وظائف مجهولة هي الإغلاق.

يتم إنشاء هذه ضمن وظائف أخرى ، وبالتالي يمكنها الوصول إلى نطاق تلك الوظيفة. هذا حتى لو تم تعيين وظيفة anonumous لمعلمة وظيفة تسمى بعد استدعاء الوظيفة الأصلية. (سأقوم بإنشاء مثال في لحظة).

type
  TAnonFunc = reference to procedure;
  TForm2 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    F1 : TAnonFunc;
    F2 : TAnonFunc;
  end;

procedure TForm2.Button1Click(Sender: TObject);
var
  a : Integer;
begin
  a := 1;

  F1 := procedure
  begin
    a := a + 1;
  end;

  F2 := procedure
  begin
    Memo1.Lines.Add(IntToStr(a));
  end;
end;

تقوم الطريقة أعلاه بتعيين وظيفتين مجهولتين للحقول F1 و F2. الأول يزيد من المتغير المحلي والعرض الثاني قيمة المتغير.

procedure TForm2.Button2Click(Sender: TObject);
begin
  F1;
end;

procedure TForm2.Button3Click(Sender: TObject);
begin
  F2;
end;

يمكنك الآن استدعاء كلتا الوظيفتين ، ويمكنهم الوصول إلى نفس أ. لذا ، فإن استدعاء F1 مرتين و F2 يعرض 3. بالطبع هذا مثال بسيط. ولكن يمكن توسيعها إلى رمز أكثر فائدة.

في بيئة الخيوط المتعددة ، يمكن استخدام وظائف مجهولة في دعوة للمزامنة ، مما يلغي الحاجة إلى طرق لا حصر لها.

قد يكون هذا المثال من بعض القيمة بالنسبة لك. هنا سأقوم بتنفيذ قائمة عرض قابلة للتكبير للرسم على tcanvas دون إعلان أنواع مختلفة من فئات العرض. كما أنه يستفيد من الأدوية الجيلية. افترض أن لدينا tform مع tpaintbox و ttrackbar عليه ...

type
  TDisplayProc = TProc<TCanvas>;

type
  TFrmExample3 = class(TForm)
    pbxMain: TPaintBox;
    trkZoom: TTrackBar;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure pbxMainClick(Sender: TObject);
    procedure pbxMainMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure pbxMainPaint(Sender: TObject);
    procedure trkZoomChange(Sender: TObject);
  private
    FDisplayList: TList<TDisplayProc>;
    FMouseX: Integer;
    FMouseY: Integer;
    FZoom: Extended;
    procedure SetZoom(const Value: Extended);
  protected
    procedure CreateCircle(X, Y: Integer);
    procedure CreateRectangle(X, Y: Integer);
    function MakeRect(X, Y, R: Integer): TRect;
  public
    property Zoom: Extended read FZoom write SetZoom;
  end;

implementation

{$R *.dfm}

procedure TFrmExample3.PaintBox1Paint(Sender: TObject);
var
  displayProc: TDisplayProc;
begin
  for displayProc in FDisplayList do
    displayProc((Sender as TPaintBox).Canvas);
end;

procedure TFrmExample3.CreateCircle(X, Y: Integer);
begin
  FDisplayList.Add(
    procedure (Canvas: TCanvas)
    begin
      Canvas.Brush.Color := clYellow;
      Canvas.Ellipse(MakeRect(X, Y, 20));
    end
  );
end;

procedure TFrmExample3.CreateRectangle(X, Y: Integer);
begin
  FDisplayList.Add(
    procedure (Canvas: TCanvas)
    begin
      Canvas.Brush.Color := clBlue;
      Canvas.FillRect(MakeRect(X, Y, 20));
    end
  );
end;

procedure TFrmExample3.FormCreate(Sender: TObject);
begin
  FDisplayList := TList<TDisplayProc>.Create;
end;

procedure TFrmExample3.FormDestroy(Sender: TObject);
begin
  FreeAndNil(FDisplayList);
end;

function TFrmExample3.MakeRect(X, Y, R: Integer): TRect;
begin
  Result := Rect(Round(Zoom*(X - R)), Round(Zoom*(Y - R)), Round(Zoom*(X + R)), Round(Zoom*(Y + R)));
end;

procedure TFrmExample3.pbxMainClick(Sender: TObject);
begin
  case Random(2) of
    0: CreateRectangle(Round(FMouseX/Zoom), Round(FMouseY/Zoom));
    1: CreateCircle(Round(FMouseX/Zoom), Round(FMouseY/Zoom));
  end;
  pbxMain.Invalidate;
end;

procedure TFrmExample3.pbxMainMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  FMouseX := X;
  FMouseY := Y;
end;

procedure TFrmExample4.SetZoom(const Value: Extended);
begin
  FZoom := Value;
  trkZoom.Position := Round(2*(FZoom - 1));
end;

procedure TFrmExample4.trkZoomChange(Sender: TObject);
begin
  Zoom := 0.5*(Sender as TTrackBar).Position + 1;
  pbxMain.Invalidate;
end;

لقد قدم الأشخاص بالفعل الرمز ، لذلك سأدرج بعض الأماكن التي يمكن أن تكون مفيدة.

قل أن لديك بعض رمز واجهة المستخدم الرسومية. عادةً ، بالنسبة لشيء يشبه معالج Onclick الخاص بزر ، يجب عليك تقديم وظيفة سيتم استدعاؤها عند النقر فوق هذا الزر. ومع ذلك ، دعنا نقول أن كل هذه الوظيفة يجب أن تفعلها شيء بسيط مثل الإطفاء عن مربع الرسائل أو تعيين حقل في مكان ما. دعنا نقول أن لديك العشرات من هذه الأزرار عبر الكود الخاص بك. بدون وظائف مجهولة ، يجب أن يكون لديك الكثير من الوظائف التي تسمى "onButton1Click" و "OnexitButtonClick" ، إلخ ، والتي من المحتمل أن تتفوق على الكود الخاص بك ... أو يمكنك إنشاء وظائف مجهولة المصدر تعلق على الفور على هذه الأحداث ، وأنت لا تضع يجب أن تقلق بشأنهم بعد الآن.

استخدام آخر هو البرمجة الوظيفية. قل أن لديك قائمة بالأرقام. تريد العودة فقط تلك الأرقام القابلة للقسمة على ثلاثة. من المحتمل أن تكون هناك وظيفة تسمى filter التي تأخذ وظيفة تُرجع منطقية وقائمة ، وإرجاع قائمة جديدة تحتوي فقط على تلك العناصر في القائمة الأولى التي ، عند نقلها إلى الوظيفة ، تم إرجاعها بشكل صحيح. مثال:

filter(isOdd, [1, 2, 3, 5, 6, 9, 10]) --> [1, 3, 5, 9]

سيكون من المزعج أن نضطر إلى تحديد وظيفة "IsdivisibleByThree" ، ثم تمريرها للتصفية ، لذلك فإن استخدامًا آخر لوظائف مجهولة هنا هو إنشاء وظيفة لن تحتاجها في أي مكان آخر للتصفية.

أنا أجيب على سؤالي الخاص ، لكنني وجدت شرحًا جيدًا لطرق مجهولة هناهل تستطيع لغة البرمجة القيام بذلك؟

أعتقد (لا أعرف دلفي) هذا يعني أنه يمكنك إنشاء وظائف كنوع من كائن البيانات الآن. هذا يعني أنه يمكنك ، على سبيل المثال ، تمرير الوظائف كمعلمات إلى وظائف أخرى. مثال: قد تأخذ وظيفة الفرز وظيفة المقارنة كمعلمة ، وبالتالي كونها أكثر تنوعا بكثير.

تعتبر الأساليب المجهولة مفيدة في البرمجة الوظيفية ، لكنها يمكن أن تساعدك أيضًا في كتابة رمز أكثر إحكاما في البرمجة المنظمة. الخيوط ، على سبيل المثال: http://blogs.codegear.com/abauer/2008/09/08/38868

حالات استخدام أخرى لـ "الإثارة" الخاصة بك :): http://delphi.fosdal.com/2008/08/anonymous-methods-when-to-use-them.html

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