1. क्षमताएं

इंटरफेस के लाभों को बेहतर ढंग से समझने के लिए और उनका उपयोग कहां करना है, हमें कुछ और अमूर्त चीजों के बारे में बात करने की जरूरत है।

एक वर्ग आमतौर पर एक विशेष वस्तु का मॉडल करता है। एक इंटरफ़ेस वस्तुओं से कम और उनकी क्षमताओं या भूमिकाओं से अधिक मेल खाता है।

इंटरफेस का सार

उदाहरण के लिए, कार, बाइक, मोटरसाइकिल और पहिए जैसी चीज़ों को कक्षाओं और वस्तुओं के रूप में सबसे अच्छा दर्शाया जाता है। लेकिन उनकी क्षमताएं - जैसे "मैं सवार हो सकता हूं", "मैं लोगों को परिवहन कर सकता हूं", "मैं खड़ा हो सकता हूं" - इंटरफेस के रूप में बेहतर प्रस्तुत किया जाता है। यहां कुछ उदाहरण दिए गए हैं:

कोड विवरण
interface CanMove
{
   void move(String newLocation);
}
स्थानांतरित करने की क्षमता के अनुरूप
interface Rideable
{
   void ride(Passenger passenger);
}
सवार होने की क्षमता के अनुरूप है
interface CanTransport
{
   void addStuff(Object stuff);
   Object removeStuff();
}
सामान ले जाने की क्षमता के अनुरूप
class Wheel implements CanMove
{
   ...
}
वर्ग चलWheel सकता है
class Car implements CanMove, Rideable, CanTransport
{
   ...
}
कक्षा चल Carसकती है , सवार हो सकती है और सामान ले जा सकती है
class Skateboard implements CanMove, Rideable
{
   ...
}
वर्ग चल Skateboardसकता है और सवार हो सकता है


2. भूमिकाएँ

इंटरफेस एक प्रोग्रामर के जीवन को बहुत सरल करते हैं। बहुत बार, एक कार्यक्रम में हजारों वस्तुएं, सैकड़ों कक्षाएं होती हैं, लेकिन सिर्फ कुछ दर्जन इंटरफेस , यानी भूमिकाएं । कुछ भूमिकाएँ हैं, लेकिन उन्हें (कक्षाओं) को संयोजित करने के कई तरीके हैं।

संपूर्ण बिंदु यह है कि आपको प्रत्येक वर्ग के लिए प्रत्येक वर्ग के साथ बातचीत करने के लिए कोड लिखने की आवश्यकता नहीं है। आपको बस उनकी भूमिकाओं (इंटरफेस) के साथ बातचीत करने की जरूरत है।

कल्पना कीजिए कि आप एक पालतू पशु प्रशिक्षक हैं। आपके साथ काम करने वाले प्रत्येक पालतू जानवर में कई अलग-अलग क्षमताएं हो सकती हैं। आप अपने पड़ोसी के साथ एक दोस्ताना बहस में पड़ जाते हैं कि किसके पालतू जानवर सबसे ज्यादा शोर कर सकते हैं। मामले को निपटाने के लिए, आप सभी पालतू जानवरों को पंक्तिबद्ध करें जो "बोल" सकते हैं, और आप उन्हें आदेश देते हैं: बोलो!

आपको परवाह नहीं है कि वे किस तरह के जानवर हैं या उनके पास और क्या क्षमताएं हैं। भले ही वे ट्रिपल बैक कलाबाज़ी कर सकते हों। इस विशेष क्षण में, आप केवल जोर से बोलने की उनकी क्षमता में रुचि रखते हैं। यहाँ यह कोड में कैसा दिखेगा:

कोड विवरण
interface CanSpeak
{
   void speak();
}
क्षमता CanSpeak। यह इंटरफ़ेस कमांड को समझता है speak, जिसका अर्थ है कि इसकी एक संबंधित विधि है।
class Cat implements CanSpeak
{
   void speak()
   {
      println("MEOW");
   }
}

class Dog implements CanSpeak
{
   void speak()
   {
      println("WOOF");
   }
}

class Fish
{
   ...
}
जिन जानवरों में यह सुविधा होती है।

समझने की सुविधा के लिए, हमने अंग्रेजी में कक्षाओं के नाम प्रदान किए। जावा में इसकी अनुमति है, लेकिन यह अत्यधिक अवांछनीय है।













हमारे पास Fishबोलने की क्षमता नहीं है ( CanSpeakइंटरफ़ेस को लागू नहीं करता है)।

public static void main(String[] args)
{
   // Add all the animals to the list
   ArrayList pets = new ArrayList();
   pets.add(new Cat());
   pets.add(new Dog());
   pets.add(new Fish());

   // If the ability exists, then make a sound
   for(Object pet: pets)
   {
      if (pet instanceof CanSpeak)
      {
         CanSpeak loudmouth = (CanSpeak) pet;
         loudmouth.speak();
      }
   }
}
और हम उन्हें कैसे आज्ञा दें?

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

और जब बहुरूपता के साथ जोड़ा जाता है, तो यह दृष्टिकोण आम तौर पर एक बड़ी सफलता होती है।



3. defaultइंटरफ़ेस विधियों का कार्यान्वयन

अमूर्त कक्षाओं में विधियों के चर और कार्यान्वयन हो सकते हैं, लेकिन उनके पास एकाधिक वंशानुक्रम नहीं हो सकता है। इंटरफेस में विधियों के चर या कार्यान्वयन नहीं हो सकते हैं, लेकिन इसमें एकाधिक विरासत हो सकती है।

स्थिति निम्न तालिका में व्यक्त की गई है:

क्षमता / संपत्ति सार कक्षाएं इंटरफेस
चर
विधि कार्यान्वयन
एकाधिक वंशानुक्रम

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

इसके अलावा, एकाधिक विरासत वाली समस्याएं मुख्य रूप से चर के कारण होती हैं। किसी भी सूरत में, उन्होंने यही तय किया और किया। JDK 8 से शुरू होकर, जावा ने इंटरफेस में विधि कार्यान्वयन को जोड़ने की क्षमता पेश की।

यहाँ एक अद्यतन तालिका है (JDK 8 और इसके बाद के संस्करण के लिए):

क्षमता / संपत्ति सार कक्षाएं इंटरफेस
चर
विधि कार्यान्वयन
एकाधिक वंशानुक्रम

अब अमूर्त वर्गों के साथ-साथ इंटरफेस के लिए, आप कार्यान्वयन के साथ या उसके बिना तरीकों की घोषणा कर सकते हैं। और यह बहुत अच्छी खबर है!

अमूर्त कक्षाओं में, कार्यान्वयन के बिना विधियों को abstractकीवर्ड से पहले होना चाहिए। कार्यान्वयन के तरीकों से पहले आपको कुछ भी जोड़ने की आवश्यकता नहीं है। इंटरफेस में, विपरीत सच है। यदि किसी विधि में कार्यान्वयन नहीं है, तो कुछ भी नहीं जोड़ा जाना चाहिए। लेकिन अगर कोई कार्यान्वयन है, तो defaultकीवर्ड अवश्य जोड़ा जाना चाहिए।

सरलता के लिए, हम इस जानकारी को निम्न तालिका में प्रस्तुत करते हैं:

क्षमता / संपत्ति सार कक्षाएं इंटरफेस
कार्यान्वयन के बिना तरीके abstract -
एक कार्यान्वयन के साथ तरीके - default

संकट

विधियों वाले इंटरफेस का उपयोग करना बड़े वर्ग पदानुक्रम को बहुत सरल बना सकता है। उदाहरण के लिए, सार InputStreamऔर OutputStreamकक्षाओं को इंटरफेस के रूप में घोषित किया जा सकता है! इससे हम उन्हें अधिक बार और अधिक आसानी से उपयोग कर सकते हैं।

लेकिन दुनिया में पहले से ही लाखों (अरबों?) जावा वर्ग हैं। और अगर आप मानक पुस्तकालयों को बदलना शुरू करते हैं, तो आप कुछ तोड़ सकते हैं। समस्त प्रकार की तरह! 😛

गलती से मौजूदा कार्यक्रमों और पुस्तकालयों को तोड़ने के लिए, यह निर्णय लिया गया कि इंटरफेस में विधि के कार्यान्वयन में सबसे कम विरासत की प्राथमिकता होगी ।

उदाहरण के लिए, यदि एक इंटरफ़ेस किसी अन्य इंटरफ़ेस को इनहेरिट करता है जिसमें एक विधि है, और पहला इंटरफ़ेस उसी विधि की घोषणा करता है, लेकिन कार्यान्वयन के बिना, तो इनहेरिट किए गए इंटरफ़ेस से विधि कार्यान्वयन इनहेरिट करने वाले इंटरफ़ेस तक नहीं पहुँचेगा। उदाहरण:

interface Pet
{
   default void meow()
   {
      System.out.println("Meow");
   }
}

interface Cat extends Pet
{
   void meow(); // Here we override the default implementation by omitting an implementation
}

class Tom implements Cat
{
}

कोड संकलित नहीं होगा क्योंकि वर्ग विधि को Tomलागू नहीं करता है ।meow()