2009-11-08 9 views
9

में func/proc से परिणाम प्राप्त करने के परिणामस्वरूप सर्वोत्तम अभ्यास डेल्फी में कार्यों/प्रक्रियाओं से सरल वस्तुओं को वापस करने के लिए क्या है?डेल्फी

उदाहरण के लिए। कोड के 2 प्रकार: संदर्भ रूप

पास बनाई गई वस्तु, प्रोक में वस्तु को पॉप्युलेट, इसे नष्ट बाद में

procedure Proc(var Obj: TMyObject); 
begin 
    // populate Obj 
end; 

O := TMyObject.Create; 
try 
    Proc(O); 
    // manipulate populated object 
finally 
    O.Free; 
end; 

या समारोह से परिणाम के रूप में बनाई गई वस्तु हो, जोड़-तोड़ के बाद नष्ट

function Func: TMyObj; 
begin 
    Result := TMyObj.Create; 
end; 

O := Func; 
if O <> nil then 
begin 
    try 
    // manipulate 
    finally 
    O.Free; 
    end; 
end; 

उत्तर

8

कोई सर्वोत्तम अभ्यास नहीं है। हालांकि, आपको प्राथमिक कार्य करना चाहिए, यह सुनिश्चित करना है कि यह हमेशा स्पष्ट होता है कि किसी भी समय ऑब्जेक्ट को नष्ट करने के लिए जिम्मेदार कौन है, भले ही अपवाद होता है।

एक नया उदाहरण बनाने और इसे वापस करने के लिए कुछ भी गलत नहीं है। ऐसा फ़ंक्शन factory है। आप इसे कक्षा के कन्स्ट्रक्टर की तरह ही इलाज कर सकते हैं, इसलिए आपको यह सुनिश्चित करना चाहिए कि यह एक कन्स्ट्रक्टर की तरह व्यवहार करता है: या तो एक वैध ऑब्जेक्ट लौटाएं या अपवाद फेंक दें। यह कभी भी एक शून्य संदर्भ देता है।

function Func: TMyObj; 
begin 
    Result := TMyObj.Create; 
    try 
    Result.X := Y; 
    except 
    Result.Free; 
    raise; 
    end; 
end; 

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

O := Func; 
try 
    writeln(O.X); 
finally 
    O.Free; 
end; 

अगर वहाँ तो O सौंप दिया जाता है कभी नहीं Func में एक अपवाद नहीं है, इसलिए करने के लिए फोन करने वाले के लिए उपलब्ध कुछ भी नहीं है मुक्त।


जब फोन करने वाले वस्तु बनाता है और आप इसे किसी अन्य कार्य करने के लिए पारित यह प्रारंभ करने, पैरामीटर "var" पैरामीटर नहीं बनाते हैं। यह कॉलर पर कुछ प्रतिबंध रखता है, जो फ़ंक्शन द्वारा अनुरोध किए गए बिल्कुल प्रकार के चर का उपयोग करना चाहिए, भले ही कुछ वंशज टाइप किए गए हों।

इस तरह के एक समारोह को ऑब्जेक्ट को मुक्त करना चाहिए। कॉलर उन कार्यों के स्वामित्व की ज़िम्मेदारी नहीं देता है, जो विशेष रूप से जब फ़ंक्शन रिटर्न के बाद ऑब्जेक्ट का उपयोग करने की योजना बनाते हैं।

+0

मुझे सीधे प्राप्त करने के लिए धन्यवाद :) महान जवाब –

4

यह वस्तु के जीवनकाल पर निर्भर करता है और इसके लिए कौन जिम्मेदार है। अधिकांश समय वस्तुओं को उसी इकाई द्वारा बनाया और नष्ट किया जाना चाहिए।

मान लें कि आपकी विधि एक फ़ाइल को पार्स करने से परिणामों के साथ एक TStringList भरती है। क्या आपको उस फ़ंक्शन को TStringList बनाने देना चाहिए, या आपको इसे बनाना चाहिए और संदर्भ के रूप में पास करना चाहिए?

मुझे इसे बनाने के लिए इसे और अधिक पठनीय लगता है, इसे संदर्भ के रूप में पास करें, और बाद में कोड की लगातार पंक्तियों में सभी को नष्ट कर दें।

अब मान लें कि आपके पास एक ऐसा कार्य है जो प्रत्येक ग्राहक के लिए एक टीसी कस्टमर देता है। उस स्थिति में मैं एक फ़ंक्शन का उपयोग करूंगा, क्योंकि मुझे लगता है कि मेरी इकाई की सूची होने पर उन्हें नष्ट करने के लिए ज़िम्मेदार ग्राहकों की एक सूची, या कुछ होगी। एक पारित कर दिया-इन संदर्भ, और एक समारोह जो उदाहरण खुद बनाता है के रूप में

-3

मैं अक्सर निर्माण

FUNCTION SomeFunction(SL : TStrings = NIL) : TStrings; 
    BEGIN 
    IF Assigned(SL) THEN Result:=SL ELSE Result:=TStringList.Create; 
    // Use Result for the remainder of the function 
    END; 

इस तरह उपयोग करते हैं, मैं के साथ एक प्रक्रिया के रूप में यह दोनों का उपयोग कर सकते हैं।

+2

-1 मुझे आपका अभ्यास बहुत भ्रमित लगता है। मैं इसके बजाय दो तरीकों का निर्माण करूंगा (एक ऑब्जेक्ट बनाने के बाद दूसरे को कॉल कर रहा हूं) और विधि का नाम स्पष्ट रूप से व्यक्त कर रहा है कि क्या हो रहा है। क्या होगा यदि आप 'कुछ कार्यक्षमता (ओबीजे)' को कॉल करना चाहते हैं, जब 'ओब्ज' आपकी विधि का पैरामीटर है? आप नहीं जानते कि यह 'शून्य' है या नहीं, इसलिए आप नहीं जानते कि आपको लौटाई गई वस्तु को मुक्त करना है या नहीं ... – jpfollenius

+0

मुझे आपकी टिप्पणी नहीं समझती है "क्या होगा यदि आप कुछ समारोह को कॉल करना चाहते हैं (Obj) जब Obj आपकी अपनी विधि का एक पैरामीटर है?आप नहीं जानते कि यह शून्य है या नहीं, इसलिए आप यह नहीं जान सकते कि आपको लौटे ऑब्जेक्ट को मुक्त करना है या नहीं .. "क्या मतलब है" जब ओब्ज आपकी विधि का पैरामीटर है? "?? यदि आप कोड उदाहरण के साथ विस्तारित हैं, तो मुझे आपको यह बताने में खुशी होगी ... – HeartWare

+0

बात यह है कि आपको तरीकों से तरीकों को लिखना चाहिए, कि हर कोई एक ही उद्देश्य परोसता है, नहीं कर रहा एक विधि में अधिक संचालन, इसलिए आपका समाधान उलझन में है और सीधा नहीं है –

2

मेरा नियम स्वामित्व और सृजन पूरी तरह से है। मेरे पास हमेशा निर्माता होता है और इस प्रकार वस्तु को नष्ट करने की उत्तरदायित्व होती है। ऑब्जेक्ट का निर्माण आमंत्रण कोड में स्पष्ट है, यह कभी भी आमंत्रण का दुष्प्रभाव नहीं होता है।

तो मेरी कार्यों की सामान्य हस्ताक्षर

function Func(o:tMyO): TMyO; 
begin 
    // .... 
    Result := o; 
end; 

इस तरह से कर रहे हैं मैं ऐसा कर सकते हैं या तो

o := func(TMyO.create); 

या

o := TMyO.create; 
    // ... 
    func(o); 
3

यह फोन करने वाले जाने के लिए एक आम डेल्फी मुहावरा है ऑब्जेक्ट बनाएं और इसे पैरामीटर के रूप में पास करें। ध्यान दें कि आपको लगभग सभी मामलों में var घोषित करने की आवश्यकता नहीं है।

procedure Proc (Obj : TMyObject) 
begin 
    Obj.SomeProperty := 'SomeValue'; 
    ... 
end; 

कॉलिंग कोड:

Obj := TMyObject.Create; 
try 
    Proc (Obj); 
finally 
    FreeAndNil (Obj); 
end;  

यह जो वस्तु मुक्त करने के लिए है के बारे में भ्रम की स्थिति से बचा जाता है। ध्यान दें कि यदि आपके पास विधि कॉल की श्रृंखला है तो यह उन वस्तुओं का ट्रैक रखने के लिए बहुत जटिल हो सकती है जिन्हें लाइन के साथ कहीं भी मुक्त किया जाना चाहिए।

एक और दोष: कोड में बिखरे सृजन और विनाश होने से try...finally ब्लॉक का उपयोग करना असंभव हो जाता है, जो संसाधन लीक से बचने के लिए एक और सहायक मुहावरे है।

यदि आप ऑब्जेक्ट बनाने के लिए अपनी विधि चाहते हैं, तो मैं इसे फ़ंक्शन नाम में स्पष्ट कर दूंगा, जैसे CreateAndInitializeList मेरे लिए सही लगता है।

1

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

हालांकि, यह केवल तभी संभव है जब कॉलर सही प्रकार के आइटम को सुपरर्ट टाइप के बजाय वापस लौटाए। उदाहरण के लिए:

var E: TEmployee; 

E := CreateEmployee(EmployeeID); // Could return TEmployee or subclasses TManager or TRetiredEmployee 

try 

    E.SendEmail(MessageText); 
    if (E is TRetiredEmployee) then 
     E.PrintLetter; 

finally 

    E.Free; 

end; 

इस तरह के मामलों में, मैं यह शब्द "बनाएँ", या अन्य सूचक, कारखाने समारोह मैं फोन कर रहा हूँ के नाम पर शामिल करने के लिए उपयोगी है पाते हैं।