2012-02-01 9 views
7

के साथ एक इंटरफ़ेस के खिलाफ कोड मैंने Why You Should Be Using Interfaces पर ब्याज निक होजेस ब्लॉग के साथ पढ़ा है और चूंकि मैं पहले से ही अपने कोडिंग में उच्च स्तर पर इंटरफेस से प्यार करता हूं, मैंने यह देखने का फैसला किया कि मैं इसे कैसे बढ़ा सकता हूं निम्न स्तर और वीसीएल कक्षाओं में इसके लिए क्या समर्थन मौजूद है इसकी जांच करने के लिए।टीएसट्रिंग्स और टीस्ट्रिंगलिस्ट

var 
    MyList : TStrings; 
    sCommaText : string; 
begin 
    MyList := TStringList.Create; 
    try 
    MyList.LoadFromFile('c:\temp\somefile.txt'); 
    sCommaText := MyList.CommaText; 

    // ... do something with sCommaText..... 

    finally 
    MyList.Free; 
    end; 
end; 

एक अच्छा सरलीकरण यदि प्रतीत होता है:

एक आम निर्माण है कि मैं की जरूरत है, इस कोड को एक अल्पविराम पाठ स्ट्रिंग में एक छोटी सी पाठ फ़ाइल सूची लोड करने के लिए कुछ एक TStringList के साथ सरल करने के लिए उदाहरण के लिए है मैं एक अंतरफलक के रूप MyList उपयोग करने के साथ लिख सकता है - यह कोशिश अंत में और सुधार पठनीयता से छुटकारा पाने होगा:

var 
    MyList : IStrings; 
     //^^^^^^^ 
    sCommaText : string; 
begin 
    MyList := TStringList.Create; 
    MyList.LoadFromFile('c:\temp\somefile.txt'); 
    sCommaText := MyList.CommaText; 

    // ... do something with sCommaText..... 

end; 

मैं एक IStrings हालांकि परिभाषित नहीं देख सकते हैं - Classes.pas में नहीं निश्चित रूप से है, हालांकि देखते हैं ओएलई प्रोग्रामिंग के संबंध में इसके संदर्भ ऑनलाइन। क्या यह अस्तित्व में है? क्या यह एक वैध सरलीकरण है? मैं डेल्फी एक्सई 2 का उपयोग कर रहा हूँ।

+4

यदि आप मेरी राय चाहते हैं: ऐसा मत करो! जैसे इंटरफेस का उपयोग कभी नहीं करना कोई समाधान नहीं है, सब कुछ के लिए इंटरफेस का उपयोग करना एक भी नहीं है। यहां तक ​​कि निक ने दावा किया है कि टीएसट्रिंग्स/टीस्ट्रिंगलिस्ट को अपने नवीनतम ब्लॉग पोस्ट में क्लास इंस्टेंस के रूप में पूरी तरह इस्तेमाल किया जा सकता है। –

+4

टीएसट्रिंग्स 'लगभग' एक इंटरफेस है, यह एक अमूर्त वर्ग है जिसमें विभिन्न कार्यान्वयन हो सकते हैं। जब भी संभव हो, मैं केवल TStrings को TStringList के बजाय पैरामीटर के प्रकार के रूप में पास करता हूं। – mjn

+0

मैं @UweRaabe से सहमत हूं। इंटरफेस शक्तिशाली हैं, और शक्तिशाली उपकरणों का अक्सर दुरुपयोग किया जाता है। किसी वस्तु संदर्भ के बजाय इंटरफ़ेस संदर्भ का उपयोग न करें क्योंकि यह संभव है। मैं इंटरफेस के मूल उद्देश्य का पालन करने की सलाह देता हूं - खुली एक्स्टेंसिबल डिज़ाइन। – kludg

उत्तर

6

आरटीएल/वीसीएल में कोई इंटरफ़ेस नहीं है जो आप चाहते हैं (उसी इंटरफ़ेस को TStrings के रूप में बेनकाब करें)। यदि आप ऐसी चीज का उपयोग करना चाहते हैं तो आपको इसे स्वयं खोजना होगा।

आप इस प्रकार का आवरण के साथ इसे लागू करना होगा:

type 
    IStrings = interface 
    function Add(const S: string): Integer; 
    end; 

    TIStrings = class(TInterfacedObject, IStrings) 
    private 
    FStrings: TStrings; 
    public 
    constructor Create(Strings: TStrings); 
    destructor Destroy; override; 
    function Add(const S: string): Integer; 
    end; 

constructor TIStrings.Create(Strings: TStrings); 
begin 
    inherited Create; 
    FStrings := Strings; 
end; 

destructor TIStrings.Destroy; 
begin 
    FStrings.Free; // don't use FreeAndNil because Nick might see this code ;-) 
    inherited; 
end; 

function TIStrings.Add(const S: string): Integer; 
begin 
    Result := FStrings.Add(S); 
end; 

स्वाभाविक रूप से आप एक असली कक्षा में TStrings इंटरफेस के बाकी लपेट होगा। इसे इस तरह एक रैपर वर्ग के साथ करें ताकि आप किसी भी प्रकार के TStrings को इसके उदाहरण तक पहुंच कर लपेट सकें।

इस तरह यह प्रयोग करें:

var 
    MyList : IStrings; 
.... 
MyList := TIStrings.Create(TStringList.Create); 

आप वास्तव में TIStrings.Create बुला के गंदे काम करने के लिए एक सहायक समारोह जोड़ना चुन सकते हैं।

ध्यान दें कि जीवनकाल एक मुद्दा हो सकता है। आप इस रैपर का एक संस्करण चाहते हैं जो अंतर्निहित TStrings उदाहरण के जीवनकाल के प्रबंधन को अधिक नहीं लेता है। इसे TIStrings कन्स्ट्रक्टर पैरामीटर के साथ व्यवस्थित किया जा सकता है।


स्वयं, मुझे लगता है कि यह एक दिलचस्प विचार प्रयोग है लेकिन वास्तव में लेने के लिए एक समझदार दृष्टिकोण नहीं है। TStrings कक्षा एक अमूर्त वर्ग है जिसमें इंटरफेस की पेशकश करने वाले सभी लाभ बहुत अधिक हैं। मैं इसका उपयोग करने के लिए कोई वास्तविक डाउनसाइड्स नहीं देखता हूं।

+4

क्यों न केवल TIStrings बनाएं। परीक्षण: TStrings डिफ़ॉल्ट प्रॉपर्टी को बिना किए बिना एक्सेस किया जा सकता है सभी तरीकों को लपेटने के लिए? –

+1

@arnaud जो कोड को बहुत अधिक गड़बड़ कर देगा क्योंकि आपको 'स्ट्रिंग्स' को बहुत कुछ लिखना होगा या स्थानीय में स्टोर करना होगा। एक डिफ़ॉल्ट संपत्ति केवल सरणी गुणों के लिए avoids। लेकिन अगर आप चाहते थे कि एक आरआईआईआई एमुलेटर था तो मुझे लगता है कि "समझदार दृष्टिकोण नहीं" के लिए –

+1

+1 अनुमान लगाने का एक अच्छा तरीका होगा!8-) – mj2008

4

चूंकि TStrings एक सार वर्ग है, इसका एक इंटरफ़ेस संस्करण अधिक प्रदान नहीं करेगा। उस इंटरफ़ेस का कोई भी कार्यान्वयन निश्चित रूप से TStrings वंशज होगा, क्योंकि कोई भी TStrings करता है सभी को फिर से लागू नहीं करना चाहता।

  1. स्वचालित संसाधन सफाई: मैं एक TStrings इंटरफ़ेस चाहने के लिए दो कारण देखते हैं। इसके लिए आपको TStrings-विशिष्ट इंटरफ़ेस की आवश्यकता नहीं है। इसके बजाय, जेसीएल से ISafeGuard इंटरफ़ेस का उपयोग करें।यहाँ एक उदाहरण है:

    var 
        G: ISafeGuard; 
        MyList: TStrings; 
        sCommaText: string; 
    begin 
        MyList := TStrings(Guard(TStringList.Create, G)); 
    
        MyList.LoadFromFile('c:\temp\somefile.txt'); 
        sCommaText := MyList.CommaText; 
    
        // ... do something with sCommaText..... 
    end; 
    

    है कि एक ही जीवन है, IMultiSafeGuard का उपयोग करना चाहिए एक से अधिक ऑब्जेक्ट को बचाने के लिए।

  2. बाह्य मॉड्यूल के साथ इंटरऑपरेक्शन। यह IStrings है। डेल्फी इसे TStringsAdapter वर्ग के साथ लागू करता है, जिसे आप GetOleStrings पर मौजूदा TStrings वंश पर कॉल करते समय वापस कर दिया जाता है। इसका उपयोग करें जब आपके पास स्ट्रिंग सूची हो और आपको IStrings या IEnumString इंटरफेस की अपेक्षा रखने वाले किसी अन्य मॉड्यूल तक पहुंच प्रदान करने की आवश्यकता हो। वे इंटरफेस अन्यथा उपयोग करने के लिए उलझन में हैं - न तो सभी चीजें TStrings करता है - इसलिए जब तक आपको करना नहीं है तब तक उनका उपयोग न करें।

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

+0

'आईएसएफ़गार्ड' जेनेरिक और टाइप-सुरक्षा के लिए रो रहा है। यह लिखने के लिए भी बहुत तुच्छ है। यदि आप पहले ही जेसीएल का उपयोग नहीं कर रहे हैं तो शायद यह प्राप्त करने के लिए जेसीएल पर निर्भरता लेना उचित नहीं है। –

+0

@Rob: एक दिलचस्प समाधान के लिए +1। अकादमिक रूप से आकर्षक लेकिन संभवतः मेरे सहकर्मियों को समझा नहीं जा सकता! –

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