इंटरफेस एक्सटेंड करने का सबसे आम उपयोग तब होता है जब पैरेंट इंटरफेस में कोई मेथड नहीं होता। उदाहरण के लिए, java.awt.event पैकेज में MouseListener इंटरफेस java.util.EventListener को एक्सटेंड करता है, जिसे इस प्रकार परिभाषित किया गया है:
उदाहरण
package java.util;
public interface EventListener {}
कोई मेथड न होने वाले इंटरफेस को टैगिंग इंटरफेस (tagging interface) या मार्कर इंटरफेस (marker interface) कहा जाता है। टैगिंग इंटरफेस के दो मूल डिजाइन उद्देश्य हैं:
1. सामान्य पैरेंट बनाना (Creates a common parent)
EventListener इंटरफेस की तरह, जिसे Java API में दर्जनों अन्य इंटरफेस द्वारा एक्सटेंड किया जाता है, आप इंटरफेस के एक समूह के बीच सामान्य पैरेंट बनाने के लिए टैगिंग इंटरफेस का उपयोग कर सकते हैं। उदाहरण के लिए, जब कोई इंटरफेस EventListener को एक्सटेंड करता है, तो JVM जानता है कि यह विशेष इंटरफेस इवेंट डेलीगेशन परिदृश्य में उपयोग किया जाएगा।
2. क्लास में डेटा टाइप जोड़ना (Adds a data type to a class)
यह वह स्थिति है जहां से "टैगिंग" शब्द आया है। एक क्लास जो टैगिंग इंटरफेस को इम्प्लीमेंट करती है, उसे कोई मेथड परिभाषित करने की आवश्यकता नहीं होती (क्योंकि इंटरफेस में कोई नहीं होता), लेकिन पॉलीमॉर्फिज्म के माध्यम से क्लास एक इंटरफेस टाइप बन जाती है।
प्रमुख मार्कर इंटरफेस (Java API में)
| इंटरफेस | पैकेज | उद्देश्य |
|---|---|---|
Serializable | java.io | क्लास को सीरियलाइज़ेबल मार्क करता है |
Cloneable | java.lang | क्लोनिंग सक्षम करता है (Object.clone()) |
Remote | java.rmi | रिमोट ऑब्जेक्ट मार्क करता है (RMI) |
EventListener | java.util | इवेंट लिस्टनर का मार्कर |
RandomAccess | java.util | कुशल रैंडम एक्सेस का संकेत (ArrayList) |
SingleThreadModel | javax.servlet | सिंगल थ्रेड मॉडल (निराशाजनक) |
उदाहरण: Serializable
import java.io.*;
class Employee implements Serializable {
private static final long serialVersionUID = 1L;
String name;
int id;
// transient फील्ड सीरियलाइज़ नहीं होगा
transient String password;
}
// सीरियलाइजेशन
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("emp.ser"))) {
oos.writeObject(new Employee("John", 1));
}
// डिसीरियलाइजेशन
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("emp.ser"))) {
Employee emp = (Employee) ois.readObject();
}
उदाहरण: Cloneable
class Student implements Cloneable {
String name;
int age;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // Shallow copy
}
}
// उपयोग
Student s1 = new Student("Alice", 20);
Student s2 = (Student) s1.clone(); // Cloneable न होने पर CloneNotSupportedException
कस्टम मार्कर इंटरफेस बनाना
// मार्कर इंटरफेस
interface Auditable {}
// उपयोग
class Transaction implements Auditable {
String id;
double amount;
}
// रनटाइम चेक
public void process(Object obj) {
if (obj instanceof Auditable) {
auditLog(obj);
}
// प्रोसेसिंग जारी रखें
}
मार्कर इंटरफेस vs एनोटेशन (आधुनिक विकल्प)
| विशेषता | मार्कर इंटरफेस | एनोटेशन |
|---|---|---|
| पैरामीटर्स | नहीं | हां (मान, डिफ़ॉल्ट, आदि) |
| मेटाडेटा समृद्धि | कम | उच्च |
| कंपाइल-टाइम प्रोसेसिंग | नहीं | हां (एनोटेशन प्रोसेसर) |
| रनटाइम रिटेंशन | हां (इंस्टेंसऑफ) | कॉन्फिगरेबल |
| विरासत | इम्प्लीमेंट्स के माध्यम से | @Inherited के माध्यम से |
एनोटेशन समकक्ष
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Auditable {}
@Auditable
class Transaction { ... }
// रनटाइम चेक
if (Transaction.class.isAnnotationPresent(Auditable.class)) { ... }
निष्कर्ष: मार्कर/टैगिंग इंटरफेस एक क्लास के लिए मेटाडेटा (टाइप टैग) जोड़ने का तरीका है बिना किसी मेथड कॉन्ट्रैक्ट के। आधुनिक Java में एनोटेशन अधिक लचीले और शक्तिशाली विकल्प हैं, लेकिन मार्कर इंटरफेस अभी भी व्यापक रूप से उपयोग किए जाते हैं (Serializable, Cloneable, आदि)।