Embarcadero Delphi
इंटरफेस
खोज…
टिप्पणियों
स्पष्ट कार्यान्वयन की जानकारी प्रदान किए बिना, आवश्यक जानकारी और विधियों और कक्षाओं के अपेक्षित आउटपुट का वर्णन करने के लिए इंटरफेस का उपयोग किया जाता है।
कक्षाएं इंटरफेस को लागू कर सकती हैं, और इंटरफेस एक दूसरे से विरासत में मिल सकते हैं। यदि कोई वर्ग इंटरफ़ेस लागू कर रहा है, तो इसका अर्थ है कि इंटरफ़ेस द्वारा उजागर किए गए सभी फ़ंक्शन और प्रक्रियाएं कक्षा में मौजूद हैं।
डेल्फी में इंटरफेस का एक विशेष पहलू यह है कि इंटरफेस के उदाहरणों का संदर्भ गिनती के आधार पर जीवन भर का प्रबंधन होता है। जीवन भर क्लास इंस्टेंसेस को मैन्युअल रूप से प्रबंधित करना होगा।
इन सभी पहलुओं को ध्यान में रखते हुए, विभिन्न लक्ष्यों को प्राप्त करने के लिए इंटरफेस का उपयोग किया जा सकता है:
- संचालन के लिए कई अलग-अलग कार्यान्वयन प्रदान करें (जैसे फ़ाइल में सहेजना, डेटाबेस या ई-मेल के रूप में भेजना, सभी इंटरफ़ेस "SaveData" के रूप में)
- निर्भरता कम करना, डिकम्पलिंग में सुधार करना और इस प्रकार कोड को बेहतर बनाए रखना और परीक्षण करना
- आजीवन प्रबंधन से परेशान हुए बिना कई इकाइयों में उदाहरणों के साथ काम करें (हालांकि यहां भी नुकसान मौजूद हैं, सावधान!)
एक इंटरफ़ेस को परिभाषित और कार्यान्वित करना
एक इंटरफ़ेस को एक वर्ग की तरह घोषित किया जाता है, लेकिन एक्सेस मॉडिफायर के बिना ( public
, private
, ...)। इसके अलावा, किसी भी परिभाषा की अनुमति नहीं है, इसलिए चर और स्थिरांक का उपयोग नहीं किया जा सकता है।
इंटरफेस में हमेशा एक विशिष्ट पहचानकर्ता होना चाहिए, जिसे Ctrl + Shift + G दबाकर उत्पन्न किया जा सकता है।
IRepository = interface
['{AFCFCE96-2EC2-4AE4-8E23-D4C4FF6BBD01}']
function SaveKeyValuePair(aKey: Integer; aValue: string): Boolean;
end;
इंटरफ़ेस लागू करने के लिए, इंटरफ़ेस का नाम आधार वर्ग के पीछे जोड़ा जाना चाहिए। इसके अलावा, वर्ग TInterfacedObject
वंशज होना चाहिए (यह जीवनकाल प्रबंधन के लिए महत्वपूर्ण है)।
TDatabaseRepository = class(TInterfacedObject, IRepository)
function SaveKeyValuePair(aKey: Integer; aValue: string): Boolean;
end;
जब कोई वर्ग इंटरफ़ेस लागू करता है, तो उसे इंटरफ़ेस में घोषित सभी विधियों और कार्यों को शामिल करना होगा, अन्यथा यह संकलन नहीं करेगा।
ध्यान देने योग्य एक बात यह है कि यदि इंटरफ़ेस के साथ कॉलर काम करता है, तो एक्सेस मॉडिफायर का कोई प्रभाव नहीं पड़ता है। उदाहरण के लिए, इंटरफ़ेस के सभी कार्यों को strict private
सदस्यों के रूप में लागू किया जा सकता है, लेकिन अगर इंटरफ़ेस का एक उदाहरण उपयोग किया जाता है, तब भी इसे दूसरे वर्ग से बुलाया जा सकता है।
कई इंटरफेस को लागू करना
कक्षाएं एक से अधिक इंटरफ़ेस को लागू कर सकती हैं, जैसा कि एक से अधिक वर्ग ( मल्टीपल इनहेरिटेंस ) से विरासत में मिला है जो डेल्फी कक्षाओं के लिए संभव नहीं है। इसे प्राप्त करने के लिए, सभी इंटरफेस के नाम को आधार वर्ग के पीछे अल्पविराम से जोड़ा जाना चाहिए।
बेशक, लागू करने वाले वर्ग को प्रत्येक इंटरफेस द्वारा घोषित कार्यों को भी परिभाषित करना चाहिए।
IInterface1 = interface
['{A2437023-7606-4551-8D5A-1709212254AF}']
procedure Method1();
function Method2(): Boolean;
end;
IInterface2 = interface
['{6C47FF48-3943-4B53-8D5D-537F4A0DEC0D}']
procedure SetValue(const aValue: TObject);
function GetValue(): TObject;
property Value: TObject read GetValue write SetValue;
end;
TImplementer = class(TInterfacedObject, IInterface1, IInterface2)
// IInterface1
procedure Method1();
function Method2(): Boolean;
// IInterface2
procedure SetValue(const aValue: TObject);
function GetValue(): TObject
property Value: TObject read GetValue write SetValue;
end;
इंटरफेस के लिए विरासत
इंटरफेसेस एक दूसरे से विरासत में मिल सकते हैं, ठीक उसी तरह जैसे क्लास भी करते हैं। एक क्रियान्वयन वर्ग को इस प्रकार इंटरफ़ेस और सभी आधार इंटरफेस के कार्यों को लागू करना है। इस तरह, हालांकि, संकलक को पता नहीं है कि अंतर्निहित वर्ग भी आधार इंटरफ़ेस को लागू करता है, यह केवल उन इंटरफेस के बारे में जानता है जो स्पष्ट रूप से सूचीबद्ध हैं। इसलिए as ISuperInterface
पर TImplementer
as ISuperInterface
उपयोग करने से काम नहीं TImplementer
। यह भी सभी आधार इंटरफेसों को स्पष्ट रूप से लागू करने के लिए सामान्य अभ्यास का परिणाम है, भी (इस मामले में TImplementer = class(TInterfacedObject, IDescendantInterface, ISuperInterface)
)।
ISuperInterface = interface
['{A2437023-7606-4551-8D5A-1709212254AF}']
procedure Method1();
function Method2(): Boolean;
end;
IDescendantInterface = interface(ISuperInterface)
['{6C47FF48-3943-4B53-8D5D-537F4A0DEC0D}']
procedure SetValue(const aValue: TObject);
function GetValue(): TObject;
property Value: TObject read GetValue write SetValue;
end;
TImplementer = class(TInterfacedObject, IDescendantInterface)
// ISuperInterface
procedure Method1();
function Method2(): Boolean;
// IDescendantInterface
procedure SetValue(const aValue: TObject);
function GetValue(): TObject
property Value: TObject read GetValue write SetValue;
end;
इंटरफेस में गुण
चूंकि इंटरफेस में चरों की घोषणा संभव नहीं है, इसलिए property Value: TObject read FValue write FValue;
को परिभाषित करने का "तेज़" तरीका ( property Value: TObject read FValue write FValue;
) का उपयोग नहीं किया जा सकता है। इसके बजाय, इंटरफ़ेस में गेट्टर और सेटर (प्रत्येक केवल यदि आवश्यक हो) भी घोषित किया जाना है।
IInterface = interface(IInterface)
['{6C47FF48-3943-4B53-8D5D-537F4A0DEC0D}']
procedure SetValue(const aValue: TObject);
function GetValue(): TObject;
property Value: TObject read GetValue write SetValue;
end;
एक बात ध्यान देने योग्य है कि कार्यान्वयन वर्ग को संपत्ति घोषित करने की आवश्यकता नहीं है। संकलक इस कोड को स्वीकार करेगा:
TImplementer = class(TInterfacedObject, IInterface)
procedure SetValue(const aValue: TObject);
function GetValue(): TObject
end;
हालाँकि, एक चेतावनी यह है कि संपत्ति को केवल इंटरफ़ेस के माध्यम से एक्सेस किया जा सकता है, केवल कक्षा के माध्यम से नहीं। साथ ही, संपत्ति को वर्ग में जोड़ने से पठनीयता बढ़ जाती है।