2008-11-01 8 views
28

कुछ अच्छी चीजों के बीच डेल्फी 200 9 में भी बेनामी विधियां मिली हैं। मैंने अज्ञात तरीकों के बारे में उदाहरण और ब्लॉग पोस्ट देखे हैं, लेकिन मुझे अभी तक उन्हें नहीं मिला है। क्या कोई समझा सकता है कि मुझे उत्साहित क्यों होना चाहिए?क्या कोई मुझे बेनामी तरीकों की व्याख्या कर सकता है?

उत्तर

11

बस ठेठ कॉलबैक कोड के बारे में सोच जहां कॉलबैक करने के लिए उपलब्ध डेटा की आवश्यकता है पाया। अक्सर इस डेटा को कॉलबैक केवल के लिए आवश्यक है, फिर भी आपको वैश्विक चर जैसे गैर-ओओपी-अनुकूल प्रथाओं से इस्तीफा देने के बिना वहां कई हुप्स से कूदना होगा। अनाम विधियों के साथ डेटा जहां रह सकता है वहां रह सकता है - आपको अनावश्यक रूप से अपने दायरे को विस्तारित करने या इसे कुछ सहायक ऑब्जेक्ट में कॉपी करने की आवश्यकता नहीं है। बस अपना कॉलबैक कोड एक अज्ञात विधि के रूप में लिखें और यह उस साइट पर सभी स्थानीय चरों को पूरी तरह से एक्सेस और कुशलतापूर्वक उपयोग कर सकता है जहां अज्ञात विधि परिभाषित की गई है (जहां इसे कहा जाता है!)।

गुमनाम तरीकों के अन्य पहलुओं, सबसे स्पष्ट रूप से तथ्य यह है कि वे कर रहे हैं, अच्छी तरह से कर रहे हैं: गुमनाम, लेकिन यह एक है कि वास्तव में उन्हें जाना मेरे लिए "क्लिक" बनाया ...

+1

यह एक टिप्पणी है जिसने मुझे 'आह' दिया है। अभी तक 100% उत्साहित नहीं है लेकिन कम से कम मैं इसके लिए वास्तविक दुनिया का उपयोग देख सकता हूं। – Steve

1

मुझे लगता है (मुझे डेल्फी नहीं पता) इसका तात्पर्य है कि आप अब एक प्रकार की डेटा ऑब्जेक्ट के रूप में कार्य कर सकते हैं। इसका मतलब है कि आप, उदाहरण के लिए, कार्यों को अन्य कार्यों के पैरामीटर के रूप में पास कर सकते हैं। उदाहरण: एक सॉर्ट फ़ंक्शन पैरामीटर के रूप में तुलना फ़ंक्शन ले सकता है, इस प्रकार अधिक बहुमुखी हो सकता है।

+1

आंशिक रूप से है। डेल्फी में पहले से ही फ़ंक्शन पॉइंटर्स हैं। लेकिन अब वे एकान्त रूप से बनाया जा सकता है। मेरी टिप्पणी देखें। –

15

कृपया closures पर एक नज़र डालें।

डेल्फी अज्ञात कार्य बंद हैं।

ये अन्य कार्यों के भीतर बनाए गए हैं और इस तरह के कार्य के दायरे तक पहुंच है। यह तब भी है जब अनौपचारिक फ़ंक्शन को फ़ंक्शन पैरामीटर को असाइन किया गया है जिसे मूल फ़ंक्शन के नाम से बुलाया जाता है। (मैं एक पल में एक उदाहरण बनाउंगा)।

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; 

अब आप दोनों कार्यों को कॉल कर सकते हैं, और वे वही एक्सेस कर सकते हैं। इसलिए एफ 1 को दो बार कॉल करना और एफ 2 एक बार दिखाता है 3. बेशक यह एक साधारण उदाहरण है। लेकिन इसे अधिक उपयोगी कोड में विस्तारित किया जा सकता है।

बहु थ्रेडिंग वातावरण में, अज्ञात कार्यों को सिंक्रनाइज़ करने के लिए कॉल में उपयोग किया जा सकता है, जो अनगिनत विधियों की आवश्यकता को समाप्त करता है।

+1

ठीक है, लेकिन मैं अभी भी उत्साहित नहीं हूँ! जेनेरिक मैं इस बारे में उत्साहित हूं क्योंकि मैं उन 100 स्थानों को देख सकता हूं जिन्हें मैं उनका उपयोग कर सकता हूं। बेनामी तरीके अभी भी मुझे ठंडा छोड़ दें। – Steve

+1

आपको उत्साहित होने की आवश्यकता नहीं है, आप उनके लिए उपयोग ढूंढेंगे ;-)। –

+0

शायद उत्साहित सही शब्द नहीं है, लेकिन मेरा मतलब यह है कि मैं एक असली दुनिया के उदाहरण (अभी तक) के बारे में नहीं सोच सकता हूं, जहां मैं कहूंगा "हां, यह वही है जो अनैमोस विधियों के लिए हैं" – Steve

1

बेनामी विधियां कार्यात्मक प्रोग्रामिंग में उपयोगी हैं, लेकिन वे आपको संरचित प्रोग्रामिंग में अधिक कॉम्पैक्ट कोड लिखने में भी मदद कर सकते हैं। थ्रेडिंग, उदाहरण के लिए: अपने 'उत्साह' :) के लिए http://blogs.codegear.com/abauer/2008/09/08/38868

एक और उपयोग के मामलों: http://delphi.fosdal.com/2008/08/anonymous-methods-when-to-use-them.html

11

हो सकता है इस उदाहरण आप के लिए कुछ मूल्य का हो सकता है। यहां मैं विभिन्न प्रकार के डिस्प्ले क्लास घोषित किए बिना टीसीएनवास पर ड्राइंग के लिए ज़ूम करने योग्य डिस्प्ले सूची लागू करने जा रहा हूं। यह जेनेरिकों का भारी उपयोग भी करता है। मान लें कि हम एक TPaintBox के साथ एक TForm और उस पर एक 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; 
5

लोग पहले से ही कोड प्रदान की है, तो मैं बस कुछ स्थानों पर जहां वे उपयोगी हो सकता है सूचीबद्ध करेंगे।

कहें कि आपके पास कुछ GUI कोड है। आम तौर पर, बटन के ऑनक्लिक हैंडलर की तरह कुछ के लिए, आपको एक फ़ंक्शन प्रदान करना होगा जिसे उस बटन पर क्लिक किया जाएगा। हालांकि, मान लें कि उस फ़ंक्शन को करना कुछ आसान है जैसे संदेश बॉक्स पॉप अप करना या कहीं भी फ़ील्ड सेट करना। मान लें कि आपके पास अपने कोड में दर्जनों बटन हैं। अज्ञात कार्यों के बिना, आपको "ऑनबटन 1 क्लिक करें," "ऑनएक्सिटबटन क्लिक," आदि नामक कई फ़ंक्शन होंगे, जो आपके कोड को अव्यवस्थित कर देंगे ... या आप अज्ञात फ़ंक्शंस बना सकते हैं जो तुरंत इन घटनाओं से जुड़ते हैं, और आप डॉन करते हैं अब उनके बारे में चिंता करने की ज़रूरत नहीं है।

एक और उपयोग कार्यात्मक प्रोग्रामिंग है। मान लें कि आपके पास संख्याओं की एक सूची है। आप केवल उन संख्याओं को वापस प्राप्त करना चाहते हैं जो तीन से विभाजित हैं।filter नामक एक फ़ंक्शन की संभावना है जो एक फ़ंक्शन लेता है जो एक बूलियन और एक सूची देता है, और एक नई सूची देता है जिसमें केवल पहली सूची में उन तत्वों को शामिल किया जाता है, जो फ़ंक्शन पर पास होने पर सत्य लौटाते हैं। उदाहरण:

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

यह कष्टप्रद हो जाएगा एक समारोह "isDivisibleByThree" को परिभाषित करने के लिए, तो फिल्टर करने के लिए इसे पारित करने के लिए मजबूर हो, तो गुमनाम कार्यों के लिए एक और उपयोग यहाँ सिर्फ जल्दी से एक समारोह बनाने के लिए किया जाएगा आप यह नहीं करेंगे कहीं और चाहिए और इसे फ़िल्टर करने के लिए पास करें।

5

मैं अपने ही सवाल का जवाब हूँ, लेकिन मैं यहाँ गुमनाम तरीकों में से एक अच्छा विवरण Can your programming language do this?

+0

+1 आईएमओ आपका उत्तर सबसे अच्छा है। – Sam

संबंधित मुद्दे

 संबंधित मुद्दे