1. इंटरफेस का परिचय
आज का दिन आपके लिए ज्ञान प्राप्ति का है। एक और नया और दिलचस्प विषय इंटरफेस है।
एक इंटरफ़ेस की अवधारणा अमूर्तता और बहुरूपता के सिद्धांतों की संतान है। एक इंटरफ़ेस एक सार वर्ग के समान है, जिसमें सभी विधियाँ सार हैं। इसे एक वर्ग के समान ही घोषित किया जाता है, लेकिन हम interface
कीवर्ड का उपयोग करते हैं।
interface Feline
{
void purr();
void meow();
void growl();
}
यहाँ इंटरफेस के बारे में कुछ उपयोगी तथ्य दिए गए हैं:
1. एक इंटरफ़ेस घोषित करना
interface Drawable
{
void draw();
}
interface HasValue
{
int getValue();
}
class
हम कीवर्ड के बजाय लिखते हैंinterface
।- इसमें केवल अमूर्त विधियाँ हैं (कीवर्ड न लिखें
abstract
) - वास्तव में, इंटरफेस में सभी
public
विधियां होती हैं
एक इंटरफ़ेस केवल इंटरफ़ेस को इनहेरिट कर सकता है। लेकिन एक इंटरफेस में कई माता-पिता हो सकते हैं। यह कहने का एक और तरीका यह है कि जावा में इंटरफेस की एकाधिक विरासत है। उदाहरण:
interface Piece extends Drawable, HasValue
{
int getX();
int getY();
}
3. इंटरफेस से विरासत में मिली कक्षाएं
एक वर्ग कई इंटरफेस (केवल एक वर्ग से) प्राप्त कर सकता है। यह implements
कीवर्ड का उपयोग करके किया जाता है। उदाहरण:
abstract class ChessItem implements Drawable, HasValue
{
private int x, y, value;
public int getValue()
{
return value;
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
}
ChessItem वर्ग को अमूर्त घोषित किया गया है: यह सभी विरासत में मिली विधियों को लागू करता है draw
। दूसरे शब्दों में, ChessItem
कक्षा में एक अमूर्त विधि होती है - draw()
.
extends
और खोजशब्दों का तकनीकी अर्थ implements
समान है: दोनों वंशानुक्रम हैं। कोड की पठनीयता में सुधार के लिए भेद किया गया था। हम यह भी कहते हैं कि कक्षाएं विरासत में मिली हैं (के माध्यम से extends
) और इंटरफेस लागू किए गए हैं (के माध्यम से implements
)
4. चर
यहाँ सबसे महत्वपूर्ण बात है: साधारण चर को इंटरफेस में घोषित नहीं किया जा सकता है (हालाँकि स्थिर वाले कर सकते हैं)।
लेकिन हमें इंटरफेस की आवश्यकता क्यों है? इनका उपयोग कब किया जाता है? कक्षाओं पर इंटरफेस के दो मजबूत फायदे हैं:
2. उनके कार्यान्वयन से "विधियों का विवरण" अलग करना।
पहले, हमने कहा था कि यदि आप अपनी कक्षा के तरीकों को अन्य वर्गों से बुलाए जाने की अनुमति देना चाहते हैं, तो आपके तरीकों को कीवर्ड से चिह्नित करने की आवश्यकता है public
। यदि आप चाहते हैं कि उनमें से कुछ विधियों को केवल आपकी कक्षा के भीतर ही बुलाया जाए, तो आपको उन्हें कीवर्ड से चिह्नित करना होगा private
। दूसरे शब्दों में, हम वर्ग के तरीकों को दो श्रेणियों में विभाजित करते हैं: "सभी के उपयोग के लिए" और "केवल हमारे अपने उपयोग के लिए"।
इंटरफेस इस विभाजन को और मजबूत करने में मदद करते हैं। हम "सभी के उपयोग के लिए एक विशेष वर्ग" के साथ-साथ एक द्वितीय श्रेणी "केवल हमारे अपने उपयोग के लिए" बनाएंगे, जो प्रथम श्रेणी को इनहेरिट करेगा। यहाँ मोटे तौर पर यह कैसा दिखेगा:
पहले | बाद |
---|---|
|
|
|
|
हम अपनी कक्षा को दो में विभाजित करते हैं: एक इंटरफ़ेस और एक वर्ग जो इंटरफ़ेस को इनहेरिट करता है । और यहाँ क्या फायदा है?
कई अलग-अलग वर्ग एक ही इंटरफ़ेस को कार्यान्वित (वारिस) कर सकते हैं। और प्रत्येक का अपना व्यवहार हो सकता है। उदाहरण के लिए, इंटरफ़ेस ArrayList
LinkedList
के दो अलग-अलग कार्यान्वयन हैं ।List
इस प्रकार, हम न केवल विभिन्न कार्यान्वयनों को छिपाते हैं, बल्कि स्वयं कार्यान्वयन वर्ग को भी छिपाते हैं (क्योंकि हमें केवल कोड में इंटरफ़ेस की आवश्यकता होती है)। यह हमें बहुत लचीला होने देता है: जैसे ही प्रोग्राम चल रहा है, हम एक वस्तु को दूसरे के साथ बदल सकते हैं, किसी वस्तु के व्यवहार को बदलने के बिना उसका उपयोग करने वाले सभी वर्गों को प्रभावित किए बिना।
बहुरूपता के साथ संयुक्त होने पर यह एक बहुत ही शक्तिशाली तकनीक है। अभी के लिए, यह स्पष्ट नहीं है कि आपको ऐसा क्यों करना चाहिए। आपको सबसे पहले दर्जनों या सैकड़ों कक्षाओं वाले कार्यक्रमों का सामना करना होगा ताकि यह समझ सकें कि इंटरफेस आपके जीवन को उनके बिना इतना आसान बना सकते हैं।
3. एकाधिक वंशानुक्रम
जावा में, सभी वर्गों में केवल एक मूल वर्ग हो सकता है। अन्य प्रोग्रामिंग भाषाओं में, कक्षाओं में अक्सर कई मूल वर्ग हो सकते हैं। यह बहुत सुविधाजनक है, लेकिन साथ ही कई समस्याएं भी लाता है।
जावा के निर्माता एक समझौते पर पहुंचे: उन्होंने कक्षाओं के एकाधिक वंशानुक्रम को मना किया, लेकिन इंटरफेस के एकाधिक वंशानुक्रम की अनुमति दी। एक इंटरफ़ेस में कई पैरेंट इंटरफ़ेस हो सकते हैं। एक क्लास में कई पैरेंट इंटरफेस हो सकते हैं लेकिन केवल एक पैरेंट क्लास।
उन्होंने कक्षाओं की एकाधिक विरासत पर प्रतिबंध क्यों लगाया लेकिन इंटरफेस की एकाधिक विरासत की अनुमति क्यों दी? तथाकथित हीरा वंशानुक्रम समस्या के कारण:
जब बी वर्ग को ए वर्ग विरासत में मिलता है, तो उसे सी और डी कक्षाओं के बारे में कुछ भी पता नहीं होता है। तो यह ए वर्ग के चर का उपयोग करता है जैसा कि यह फिट दिखता है। C वर्ग वही करता है: यह A वर्ग के चर का उपयोग करता है, लेकिन एक अलग तरीके से। और यह सब डी वर्ग में संघर्ष का परिणाम है।
आइए निम्नलिखित सरल उदाहरण देखें। मान लें कि हमारे पास 3 वर्ग हैं:
class Data
{
protected int value;
}
class XCoordinate extends Data
{
public void setX (int x) { value = x;}
public int getX () { return value;}
}
class YCoordinate extends Data
{
public void setY (int y) { value = y;}
public int getY () { return value; }
}
डेटा वर्ग value
चर को संग्रहीत करता है। इसका एक्सकोर्डिनेट वंशज वर्ग मूल्य को संग्रहीत करने के लिए उस चर का उपयोग करता है x
, और YCoordinate
वंश वर्ग इसका उपयोग y
मूल्य को संग्रहीत करने के लिए करता है।
और यह काम करता है। अलग से। लेकिन अगर हम चाहते हैं कि XYCoordinates वर्ग दोनों XCoordinate
और YCoordinate
वर्गों को इनहेरिट करे, तो हमें टूटा हुआ कोड मिलता है। इस वर्ग के पास अपने पूर्वज वर्ग के तरीके होंगे, लेकिन वे सही तरीके से काम नहीं करेंगे, क्योंकि उनके पास समान हैं value variable
।
लेकिन क्योंकि इंटरफेस में वेरिएबल्स नहीं हो सकते हैं, उनके पास इस तरह का विरोध नहीं हो सकता है। तदनुसार, इंटरफेस की एकाधिक विरासत की अनुमति है।
GO TO FULL VERSION