यह उत्तर एक अमूर्त वर्ग और एक अंतरफलक के बीच के अंतर को समझाने का एक अच्छा काम करता है , लेकिन यह जवाब नहीं देता है कि आपको एक क्यों घोषित करना चाहिए।
विशुद्ध रूप से तकनीकी दृष्टिकोण से, एक वर्ग को सार घोषित करने की आवश्यकता कभी नहीं होती है ।
निम्नलिखित तीन वर्गों पर विचार करें:
class Database {
public String[] getTableNames() { return null; } //or throw an exception? who knows...
}
class SqlDatabase extends Database { } //TODO: override getTableNames
class OracleDatabase extends Database { } //TODO: override getTableNames
आपको डेटाबेस वर्ग को अमूर्त बनाने की आवश्यकता नहीं है , भले ही इसके कार्यान्वयन में एक स्पष्ट समस्या है: जब आप इस कार्यक्रम को लिख रहे हैं, तो आप टाइप कर सकते हैं new Database()
और यह मान्य होगा, लेकिन यह कभी काम नहीं करेगा।
भले ही, आप अभी भी बहुरूपता प्राप्त करेंगे, इसलिए जब तक आपका कार्यक्रम केवल बनाता है SqlDatabase
और OracleDatabase
उदाहरण देता है, आप निम्न तरीके लिख सकते हैं:
public void printTableNames(Database database) {
String[] names = database.getTableNames();
}
सार वर्ग किसी डेवलपर को आधार वर्ग को तत्काल रोककर स्थिति में सुधार करता है , क्योंकि एक डेवलपर ने इसे लापता कार्यक्षमता होने के रूप में चिह्नित किया है । यह संकलित समय सुरक्षा भी प्रदान करता है ताकि आप यह सुनिश्चित कर सकें कि आपके अमूर्त वर्ग का विस्तार करने वाले किसी भी वर्ग को काम करने के लिए नंगे न्यूनतम कार्यक्षमता प्रदान करें, और आपको स्टब विधियों (जैसे ऊपर वाले) के बारे में चिंता करने की आवश्यकता नहीं है जो विरासत में किसी तरह है जादुई को पता है कि वे है ताकि इसे काम करने के लिए एक विधि ओवरराइड करने के लिए।
इंटरफेस एक पूरी तरह से अलग विषय है। एक इंटरफ़ेस आपको यह वर्णन करने देता है कि किसी ऑब्जेक्ट पर कौन से ऑपरेशन किए जा सकते हैं। जब आप अन्य घटकों, वस्तुओं की सेवाओं का उपयोग करते हैं, तो आप आमतौर पर इंटरफेस का उपयोग करते हैं, लेकिन आप इस बात की परवाह नहीं करते हैं कि आपको किस प्रकार की वस्तु मिल रही है।
निम्नलिखित विधि पर विचार करें:
public void saveToDatabase(IProductDatabase database) {
database.addProduct(this.getName(), this.getPrice());
}
आप इस बात की परवाह नहीं करते हैं कि database
वस्तु किसी विशेष वस्तु से विरासत में मिली है या नहीं, आप केवल इस बात की परवाह करते हैं कि यह एक addProduct
विधि है। तो इस मामले में, एक इंटरफ़ेस आपके सभी वर्गों को एक ही आधार वर्ग से विरासत में लेने से बेहतर है।
कभी-कभी दोनों का संयोजन बहुत अच्छी तरह से काम करता है। उदाहरण के लिए:
abstract class RemoteDatabase implements IProductDatabase {
public abstract String[] connect();
public abstract void writeRow(string col1, string col2);
public void addProduct(String name, Double price) {
connect();
writeRow(name, price.toString());
}
}
class SqlDatabase extends RemoteDatabase {
//TODO override connect and writeRow
}
class OracleDatabase extends RemoteDatabase {
//TODO override connect and writeRow
}
class FileDatabase implements IProductDatabase {
public void addProduct(String name, Double price) {
//TODO: just write to file
}
}
ध्यान दें कि कुछ कार्यक्षमता साझा करने के लिए रिमोटडेटाबेस से कुछ डेटाबेस कैसे प्राप्त होते हैं (जैसे कि पंक्ति लिखने से पहले कनेक्ट करना), लेकिन फाइलडाबेस अलग वर्ग है जो केवल लागू करता है IProductDatabase
।