उदाहरण के लिए, मान लें कि मुझे एक ICar
इंटरफ़ेस चाहिए और सभी कार्यान्वयन में फ़ील्ड शामिल होगा Year
। क्या इसका मतलब यह है कि प्रत्येक कार्यान्वयन को अलग से घोषित करना होगा Year
? यह केवल इंटरफ़ेस में इसे परिभाषित करने के लिए अच्छा नहीं होगा?
उदाहरण के लिए, मान लें कि मुझे एक ICar
इंटरफ़ेस चाहिए और सभी कार्यान्वयन में फ़ील्ड शामिल होगा Year
। क्या इसका मतलब यह है कि प्रत्येक कार्यान्वयन को अलग से घोषित करना होगा Year
? यह केवल इंटरफ़ेस में इसे परिभाषित करने के लिए अच्छा नहीं होगा?
जवाबों:
हालाँकि, कई अन्य उत्तर सिमेंटिक स्तर पर सही हैं, लेकिन मुझे यह भी दिलचस्प लगता है कि कार्यान्वयन विवरण के स्तर से इस प्रकार के प्रश्नों पर संपर्क करें।
एक इंटरफ़ेस को स्लॉट्स के संग्रह के रूप में सोचा जा सकता है , जिसमें विधियां शामिल हैं । जब एक क्लास एक इंटरफ़ेस लागू करता है, तो क्लास को रनटाइम बताने की आवश्यकता होती है कि सभी आवश्यक स्लॉट कैसे भरें। जब आप कहें
interface IFoo { void M(); }
class Foo : IFoo { public void M() { ... } }
वर्ग कहता है "जब आप मेरे बारे में एक उदाहरण बनाते हैं, तो IFoo.M के लिए स्लॉट में Foo.M का संदर्भ दें।
तब जब आप कॉल करते हैं:
IFoo ifoo = new Foo();
ifoo.M();
कंपाइलर कोड बनाता है जो कहता है कि "ऑब्जेक्ट से पूछें कि IFoo.M के लिए स्लॉट में क्या विधि है, और उस विधि को कॉल करें।
यदि एक इंटरफ़ेस स्लॉट्स का एक संग्रह होता है जिसमें विधियाँ होती हैं, तो उनमें से कुछ स्लॉट्स में किसी गुण के प्राप्त करने और सेट करने के तरीके, इंडेकर के प्राप्त करने और सेट करने के तरीके और किसी ईवेंट के तरीकों को जोड़ने और हटाने के तरीके शामिल हो सकते हैं। लेकिन एक क्षेत्र एक विधि नहीं है । फ़ील्ड के साथ कोई "स्लॉट" जुड़ा नहीं है जिसे आप फ़ील्ड स्थान के संदर्भ में "भर सकते हैं"। और इसलिए, इंटरफेस विधियों, गुणों, अनुक्रमकों और घटनाओं को परिभाषित कर सकते हैं, लेकिन फ़ील्ड नहीं।
An interface cannot contain constants, fields, operators
। msdn.microsoft.com/en-us/library/ms173156.aspx )
int One()
, तो कार्यान्वयन public int One(){return 1;}
एक क्षेत्र नहीं है।
सी # में इंटरफेस का उद्देश्य अनुबंध को परिभाषित करना है जो एक वर्ग का पालन करेगा - एक विशेष कार्यान्वयन नहीं।
उस भावना में, C # इंटरफेस गुणों को परिभाषित करने की अनुमति देते हैं - जिसके लिए कॉलर को एक कार्यान्वयन की आपूर्ति करनी चाहिए:
interface ICar
{
int Year { get; set; }
}
कार्यान्वयन को आसान बनाने के लिए कक्षाएं लागू करने से ऑटो-संपत्तियों का उपयोग किया जा सकता है, अगर संपत्ति से जुड़ा कोई विशेष तर्क नहीं है:
class Automobile : ICar
{
public int Year { get; set; } // automatically implemented
}
Year
?
public int Year => 123;
। हालाँकि, इस मामले में इसका कोई मतलब नहीं है कि एक सेटर है, इसलिए इंटरफ़ेस को परिभाषित करना होगाint Year { get; }
एरिक लिपर्ट ने इसका उल्लेख किया, मैं यह कहने के लिए एक अलग तरीके का उपयोग करूंगा कि उन्होंने क्या कहा। एक इंटरफ़ेस के सभी सदस्य आभासी हैं और उन्हें उन सभी को एक वर्ग द्वारा अधिलेखित करने की आवश्यकता है जो इंटरफ़ेस को विरासत में लेते हैं। आप इंटरफ़ेस घोषणा में वर्चुअल कीवर्ड को स्पष्ट रूप से नहीं लिखते हैं, और न ही कक्षा में ओवरराइड कीवर्ड का उपयोग करते हैं, वे निहित हैं।
वर्चुअल कीवर्ड .NET में विधियों और तथाकथित v- तालिका, विधि बिंदुओं की एक सरणी के साथ कार्यान्वित किया जाता है। ओवरराइड कीवर्ड एक अलग विधि सूचक के साथ वी-टेबल स्लॉट को भरता है, जो बेस क्लास द्वारा निर्मित एक को ओवरराइट करता है। गुण, घटनाओं और सूचकांक को हुड के तहत तरीकों के रूप में लागू किया जाता है। लेकिन खेत नहीं हैं। इसलिए इंटरफ़ेस में फ़ील्ड नहीं हो सकते हैं।
सिर्फ एक Year
संपत्ति क्यों नहीं है , जो पूरी तरह से ठीक है?
फ़ील्ड में फ़ील्ड शामिल नहीं हैं क्योंकि फ़ील्ड डेटा प्रतिनिधित्व का एक विशिष्ट कार्यान्वयन का प्रतिनिधित्व करते हैं, और उन्हें उजागर करने से एन्कैप्सुलेशन टूट जाएगा। इस प्रकार एक क्षेत्र के साथ एक इंटरफ़ेस प्रभावी रूप से एक इंटरफ़ेस के बजाय कार्यान्वयन के लिए कोडिंग होगा, जो एक इंटरफ़ेस के लिए एक उत्सुक विरोधाभास है!
उदाहरण के लिए, आपके Year
विनिर्देशन के भाग के लिए यह आवश्यक हो सकता है कि यह ICar
कार्यान्वयनकर्ताओं के लिए अमान्य हो, Year
जो वर्तमान वर्ष + 1 या 1900 से पहले असाइनमेंट की अनुमति देता है। यह कहने का कोई तरीका नहीं है कि यदि आपने Year
खेतों को उजागर किया था - तो उपयोग करने के लिए बेहतर है यहाँ काम करने के बजाय गुण।
संक्षिप्त उत्तर हां है, प्रत्येक कार्यान्वयन प्रकार को अपना स्वयं का बैकिंग वैरिएबल बनाना होगा। ऐसा इसलिए है क्योंकि एक इंटरफ़ेस एक अनुबंध के अनुरूप है। सभी यह कर सकते हैं कि कोड के विशेष रूप से सार्वजनिक रूप से सुलभ टुकड़े निर्दिष्ट करें कि एक कार्यान्वयन प्रकार को उपलब्ध कराना चाहिए; इसमें कोई भी कोड नहीं हो सकता है।
इस परिदृश्य पर विचार करें कि आप क्या सुझाव देते हैं:
public interface InterfaceOne
{
int myBackingVariable;
int MyProperty { get { return myBackingVariable; } }
}
public interface InterfaceTwo
{
int myBackingVariable;
int MyProperty { get { return myBackingVariable; } }
}
public class MyClass : InterfaceOne, InterfaceTwo { }
हमारे यहाँ कुछ समस्याएं हैं:
myBackingVariable
करेगा MyClass
?लिया गया सबसे आम तरीका है इंटरफ़ेस को घोषित करना और इसे लागू करने वाले एक नंगे पैर अमूर्त वर्ग। यह आपको अमूर्त वर्ग से विरासत में मिलने वाले लचीलेपन की अनुमति देता है और मुक्त करने के लिए कार्यान्वयन प्राप्त कर रहा है, या स्पष्ट रूप से इंटरफ़ेस को लागू करने और किसी अन्य वर्ग से प्राप्त करने की अनुमति दी जा रही है। यह कुछ इस तरह काम करता है:
public interface IMyInterface
{
int MyProperty { get; set; }
}
public abstract class MyInterfaceBase : IMyInterface
{
int myProperty;
public int MyProperty
{
get { return myProperty; }
set { myProperty = value; }
}
}
दूसरों ने 'क्यों' दिया है, इसलिए मैं सिर्फ इतना जोड़ूंगा कि आपका इंटरफ़ेस नियंत्रण को परिभाषित कर सकता है; यदि आप इसे एक संपत्ति में लपेटते हैं:
public interface IView {
Control Year { get; }
}
public Form : IView {
public Control Year { get { return uxYear; } } //numeric text box or whatever
}
इंटरफेस में कोई कार्यान्वयन नहीं है।
पहले से ही बहुत कुछ कहा गया है, लेकिन इसे सरल बनाने के लिए, यहाँ मेरा लेना है। इंटरफेस का उद्देश्य उपभोक्ताओं या वर्गों द्वारा लागू किए जाने वाले विधि अनुबंधों और मूल्यों को संग्रहीत करने के लिए फ़ील्ड नहीं रखना है।
आप तर्क दे सकते हैं कि तब संपत्तियों की अनुमति क्यों है? तो सरल उत्तर है - गुणों को आंतरिक रूप से केवल तरीकों के रूप में परिभाषित किया जाता है।
इसके लिए आपके पास एक कार बेस क्लास हो सकता है जो वर्ष क्षेत्र को लागू करता है, और अन्य सभी कार्यान्वयन इससे विरासत में मिल सकते हैं।
एक इंटरफ़ेस सार्वजनिक उदाहरण गुणों और विधियों को परिभाषित करता है । फ़ील्ड आमतौर पर निजी होती हैं, या सबसे अधिक संरक्षित, आंतरिक या संरक्षित आंतरिक (शब्द "फ़ील्ड" आमतौर पर सार्वजनिक रूप से उपयोग नहीं की जाती है)।
जैसा कि अन्य उत्तरों द्वारा कहा गया है कि आप एक आधार वर्ग को परिभाषित कर सकते हैं और एक संरक्षित संपत्ति को परिभाषित कर सकते हैं जो सभी उत्तराधिकारियों द्वारा सुलभ होगी।
एक विषमता यह है कि एक इंटरफ़ेस को वास्तव में आंतरिक के रूप में परिभाषित किया जा सकता है लेकिन यह इंटरफ़ेस की उपयोगिता को सीमित करता है, और इसका उपयोग आमतौर पर आंतरिक कार्यक्षमता को परिभाषित करने के लिए किया जाता है जो अन्य बाहरी कोड द्वारा उपयोग नहीं किया जाता है।