2013-04-25 7 views
13

लागू करता है मैं उम्मीद करता हूं कि संदर्भ गणना को इंटरफेस कार्यान्वयन में बाहरी समेकित वस्तु पर काम करना चाहिए। मैं एक और उदाहरण का उल्लेख कर सकते हैं: Clarity in classes implementing multiple interfaces (alternative to delegation):डेल्फी इंटरफेस

यहाँ व्यवहार का एक न्यूनतम प्रजनन है:

program SO16210993; 

{$APPTYPE CONSOLE} 

type 
    IFoo = interface 
    procedure Foo; 
    end; 

    TFooImpl = class(TInterfacedObject, IFoo) 
    procedure Foo; 
    end; 

    TContainer = class(TInterfacedObject, IFoo) 
    private 
    FFoo: IFoo; 
    public 
    constructor Create; 
    destructor Destroy; override; 
    property Foo: IFoo read FFoo implements IFoo; 
    end; 

procedure TFooImpl.Foo; 
begin 
    Writeln('TFooImpl.Foo called'); 
end; 

constructor TContainer.Create; 
begin 
    inherited; 
    FFoo := TFooImpl.Create; 
end; 

destructor TContainer.Destroy; 
begin 
    Writeln('TContainer.Destroy called');//this line never runs 
    inherited; 
end; 

procedure Main; 
var 
    Foo : IFoo; 
begin 
    Foo := TContainer.Create; 
    Foo.Foo; 
end; 

begin 
    Main; 
    Readln; 
end. 

implements उपयोग करने के बजाय, मैं तो नाशक रन TImplementor कक्षा में इंटरफ़ेस को लागू।

+5

"क्या मुझे कुछ याद आ रहा है?" मुझे नहीं पता। लेकिन हम निश्चित रूप से हैं। आप कोड शामिल करना भूल गए! व्यवहार का प्रदर्शन करने वाला पूरा कार्यक्रम आवश्यक है। अन्यथा हमें अनुमान लगाना होगा। –

+1

आपके पास कुछ अतिरिक्त संदर्भ या संदर्भ लूप हैं। TFirstSecond._AddRef और TFirstSecond._Release के लिए ओवरराइड जोड़ें और वहां ब्रेकपॉइंट्स डालें, संदर्भों की पूरी सूची प्राप्त करें और देखें कि कौन से को साफ़ नहीं किया गया –

+0

अच्छा, समस्या यह है कि आपके इंटरफेस को प्रतिनिधि दिया जाता है। यकीन नहीं है कि यह इस व्यवहार का कारण बनता है। –

उत्तर

15

यहाँ क्या हो रहा है कि आप TContainer.Create फोन और एक वस्तु के लिए एक उदाहरण पैदा करते हैं। लेकिन फिर आप उस आवृत्ति को इंटरफ़ेस संदर्भ, वैश्विक चर Foo पर असाइन करते हैं। क्योंकि उस चर प्रकार IFoo की है, इंटरफ़ेस प्रतिनिधिमंडल को लागू करने का मतलब है कि वस्तु TFooImpl और नहींTContainer के कहने का उदाहरण है।

इसलिए कुछ भी नहीं कभी TContainer के कहने के लिए एक संदर्भ लेता है, उसके संदर्भ गिनती में वृद्धि हुई है कभी नहीं है, और इसलिए इसे नष्ट कर दिया कभी नहीं है।

मुझे नहीं लगता कि इसके आसपास एक बहुत ही आसान तरीका है। आप TAggregatedObject का उपयोग करने में सक्षम हो सकते हैं लेकिन यह आपकी समस्या का समाधान नहीं कर सकता है। यह TContainer.FFoo को TFooImpl के प्रकार घोषित करने के लिए मजबूर करेगा जो मुझे लगता है कि आप नहीं करना चाहते हैं। किसी भी तरह, यहाँ यह कैसा फिर से डाली कि जिस तरह से दिखाई देता है:

program SO16210993_TAggregatedObject; 

{$APPTYPE CONSOLE} 

type 
    IFoo = interface 
    procedure Foo; 
    end; 

    TFooImpl = class(TAggregatedObject, IFoo) 
    procedure Foo; 
    end; 

    TContainer = class(TInterfacedObject, IFoo) 
    private 
    FFoo: TFooImpl; 
    function GetFoo: IFoo; 
    public 
    destructor Destroy; override; 
    property Foo: IFoo read GetFoo implements IFoo; 
    end; 

procedure TFooImpl.Foo; 
begin 
    Writeln('TFooImpl.Foo called'); 
end; 

destructor TContainer.Destroy; 
begin 
    Writeln('TContainer.Destroy called');//this line does run 
    FFoo.Free; 
    inherited; 
end; 

function TContainer.GetFoo: IFoo; 
begin 
    if not Assigned(FFoo) then 
    FFoo := TFooImpl.Create(Self); 
    Result := FFoo; 
end; 

procedure Main; 
var 
    Foo : IFoo; 
begin 
    Foo := TContainer.Create; 
    Foo.Foo; 
end; 

begin 
    Main; 
    Readln; 
end. 

documentation इस बारे में बात करता है:

वर्ग आप प्रत्यायोजित इंटरफ़ेस TAggregationObject से निकाले जाते हैं चाहिए लागू करने के लिए इस्तेमाल करते हैं।

प्रारंभ में मुझे इस TAggregationObject के लिए कोई दस्तावेज नहीं मिला। और अंत में मुझे एहसास हुआ कि वास्तव में इसे TAggregatedObject नाम दिया गया है और documented है।

TAggregatedObject को नियंत्रित करने के लिए IInterface को सौंपने के लिए IInterface तरीकों को लागू करने से एक कुल का एक आंतरिक वस्तु के लिए सुविधा प्रदान करता है।

एकत्रित वस्तु कई interfaced वस्तुओं से बना एक वस्तु है। प्रत्येक वस्तु अपने स्वयं के व्यवहार और इंटरफेस लागू करती है, लेकिन सभी ऑब्जेक्ट्स समान संदर्भ गणना साझा करते हैं, जो नियंत्रक ऑब्जेक्ट का है। कंटेनर पैटर्न में, नियंत्रक कंटेनर ऑब्जेक्ट है।

TAggregatedObject स्वयं किसी भी इंटरफेस का समर्थन नहीं करता है। हालांकि, कुल मिलाकर सामान्य है, यह IInterface के तरीकों को लागू करता है, जिसका उपयोग उन वस्तुओं से किया जाता है जो इससे निकलते हैं। TAggregatedObject, इसलिए, कक्षाओं कि वस्तुओं है कि एक कुल का हिस्सा हैं बनाने के लिए इंटरफेस को लागू करने के लिए एक आधार के रूप में कार्य करता है।

TAggregatedObject कि वस्तुओं और जोड़ने वस्तुओं निहित बनाने वर्गों के लिए एक आधार के रूप में प्रयोग किया जाता है।TAggregatedObject का उपयोग करना सुनिश्चित करता है कि कुल के IInterface को नियंत्रित करने वाले IInterface विधियों को कॉल करता है।

नियंत्रण IInterface TAggregatedObject के लिए निर्माता में निर्दिष्ट है और नियंत्रक संपत्ति द्वारा इंगित किया गया है।

इसके अलावा वहाँ स्रोत कोड टिप्पणियों से यह है:

TAggregatedObject और TContainedObject एकत्रित किया या समाहित किया जाना करने के लिए एक बाहरी नियंत्रित वस्तु में इरादा interfaced वस्तुओं के लिए उपयुक्त आधार वर्ग हैं। बाहरी ऑब्जेक्ट क्लास घोषणा में इंटरफ़ेस प्रॉपर्टी पर "लागू" वाक्यविन्यास का उपयोग करते समय, आंतरिक ऑब्जेक्ट को लागू करने के लिए इन प्रकारों का उपयोग करें।

नियंत्रक की तरफ से समेकित वस्तुओं द्वारा कार्यान्वित इंटरफेस नियंत्रक द्वारा प्रदत्त अन्य इंटरफेस से अलग नहीं होना चाहिए। समेकित वस्तुओं को अपने स्वयं के संदर्भ गणना को बनाए रखना नहीं चाहिए - उनके पास उनके नियंत्रक के समान जीवनकाल होना चाहिए। इसे प्राप्त करने के लिए, समेकित वस्तुएं नियंत्रक को संदर्भ गणना विधियों को प्रतिबिंबित करती हैं।

TAggregatedObject बस अपने नियंत्रक को क्वेरी इंटेरफेस कॉल को प्रतिबिंबित करता है। इस तरह की एक समेकित वस्तु से, कोई भी इंटरफ़ेस प्राप्त कर सकता है जो नियंत्रक समर्थन करता है, और केवल नियंत्रक का समर्थन करता है। यह नियंत्रक कक्षा को कार्यान्वित करने के लिए उपयोगी है जो नियंत्रक वर्ग पर घोषित इंटरफेस को लागू करने के लिए एक या अधिक आंतरिक ऑब्जेक्ट्स का उपयोग करता है। एकत्रीकरण ऑब्जेक्ट पदानुक्रम में कार्यान्वयन साझाकरण को बढ़ावा देता है।

टीएग्रेगेटेड ऑब्जेक्ट सबसे अधिक ऑब्जेक्ट्स को से प्राप्त करना चाहिए, खासकर जब "उपकरण" वाक्यविन्यास के संयोजन के साथ उपयोग किया जाता है।

+0

@FabricioAraujo मुझे अंत में दस्तावेज़ मिल गए। एक टाइपो था !! –

+0

मैं कहीं और पाया अनगिनत उदाहरणों से गुमराह था। यह सही समझ में आता है कि संदर्भ गणना कहीं और होनी चाहिए। – Gryffe

+0

का उत्तर देने के लिए धन्यवाद आपका स्वागत है। यह मेरे लिए एक दिलचस्प सीखने का अनुभव था! –

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