विचार स्वयं ही ध्वनि है। लेकिन यह काम नहीं करेगा, अगर आप रूट प्रकार (यहां: NumberSet
) पैकेज निजी बनाते हैं। या तो उस प्रकार का पर्दाफाश करें या इसके बजाय सार्वजनिक इंटरफ़ेस का उपयोग करें। वास्तविक कार्यान्वयन प्रकारों को छुपाया जाना चाहिए (और कर सकते हैं)।
public abstract class NumberSet {
// Constructor is package private, so no new classes can be derived from
// this guy outside of its package.
NumberSet() {
}
}
public class Factories {
public NumberSet range(int start, int length) {
return new RangeNumberSet(start, length);
}
// ...
}
class RangeNumberSet extends NumberSet {
// ... must be defined in the same package as NumberSet
// Is "invisible" to client code
}
संपादित एक सार्वजनिक एपीआई से एक छिपा/निजी जड़ प्रकार का पर्दाफाश करने के लिए एक गलती है। इस परिदृश्य पर विचार करें:
package example;
class Bar {
public void doSomething() {
// ...
}
}
public class Foo {
public Bar newBar() {
return new Bar();
}
}
और इस एपीआई का उपयोग कर एक ग्राहक आवेदन पर विचार करें। ग्राहक क्या कर सकता है? यह टाइप Bar
टाइप करने के लिए एक चर घोषित नहीं कर सकता है क्योंकि उस प्रकार पैकेज example
के बाहर किसी भी वर्ग के लिए अदृश्य है। Bar
उदाहरण पर यह public
विधियों को भी कॉल नहीं कर सकता है, क्योंकि यह पता नहीं है कि ऐसी सार्वजनिक विधि मौजूद है (यह वर्ग नहीं देख सकती है, इसे किसी भी सदस्य को उजागर करने दें)।
Object bar = foo.newBar();
जो अनिवार्य रूप से बेकार है: तो, सबसे अच्छा एक ग्राहक यहाँ कर सकते हैं की तरह कुछ है। उपरोक्त परिभाषित कोड में, निजी पैकेज के बजाय सार्वजनिक इंटरफेस (या अमूर्त वर्ग) की एक अलग बात होगी। इस मामले में, ग्राहक वास्तव में NumberSet
प्रकार का एक चर घोषित कर सकता है। यह अपने स्वयं के उदाहरण नहीं बना सकता है या सबक्लास प्राप्त नहीं कर सकता है, क्योंकि कन्स्ट्रक्टर इससे छिपा हुआ है, लेकिन यह परिभाषित सार्वजनिक एपीआई तक पहुंच सकता है।
संपादित करें फिर आप एक "कुरूप" मूल्य (ग्राहक के नजरिए से), यानी, एक मूल्य है, जो किसी भी दिलचस्प एपीआई ग्राहक को परिभाषित नहीं करता, कॉल करने के लिए चाहते हो सकता है यह अभी भी करने के लिए एक अच्छा विचार है चाहते हैं यहां तक कि अगर ऊपर वर्णित तरीके से एक सार्वजनिक आधार प्रकार का पर्दाफाश करें। और यह केवल कंपाइलर के प्रकार के लिए जांचने में सक्षम है और क्लाइंट कोड को अस्थायी रूप से इस तरह के मान को एक (उचित रूप से घोषित) चर में स्टोर करने की अनुमति देता है।
यदि आप नहीं चाहते हैं कि आपका ग्राहक इस प्रकार के किसी भी एपीआई विधियों को कॉल करे: यह ठीक है। आपके (अन्यथा) सार्वजनिक आधार प्रकार पर सार्वजनिक एपीआई प्रदान न करने से आपको कुछ भी नहीं रोक रहा है। बस किसी को घोषित न करें। एक "खाली" अमूर्त बेस क्लास (क्लाइंट के परिप्रेक्ष्य से खाली, का उपयोग करें, क्योंकि सभी रोचक विधियां निजी पैकेज होंगी और इस तरह छिपी होंगी)। लेकिन आपको सार्वजनिक आधार प्रकार की आपूर्ति करना है, फिर भी आपको सादे Object
का उपयोग वापसी मूल्य के रूप में करना चाहिए, लेकिन फिर आप संकलन समय पर त्रुटि जांच को जब्त कर लेते हैं।
अंगूठे का नियम: यदि ग्राहक को कोई मूल्य प्राप्त करने के लिए कुछ विधि कॉल करना है और इसे किसी अन्य एपीआई पर पास करना है, तो क्लाइंट वास्तव में जानता है, कि कुछ जादू विशेष मूल्य हैं। और इसे किसी भी तरह से इसे संभालने में सक्षम होना चाहिए (कम से कम इसे "पास करें")। मूल्यों से निपटने के लिए ग्राहक के लिए उचित प्रकार प्रदान नहीं करना आपको संकलक चेतावनियों को पूरी तरह से उचित (पूरी तरह उचित) छोड़कर कुछ भी नहीं खरीदता है।
public abstract class Specification {
Specification() {
// Package private, thus not accessible to the client
// No subclassing possible
}
Stuff getInternalValue1() {
// Package private, thus not accessible to the client
// Client cannot call this
}
}
उपरोक्त वर्ग क्लाइंट कोड के संबंध में "खाली" है; यह सामान को छोड़कर एक प्रयोग योग्य एपीआई प्रदान नहीं करता है, जो Object
पहले से ही ऑफर करता है। इसे रखने का प्रमुख लाभ: ग्राहक इस प्रकार के चर घोषित कर सकता है, और संकलक चेक टाइप करने में सक्षम है। आपका ढांचा, हालांकि, एकमात्र जगह बनी हुई है, जहां इस प्रकार के ठोस उदाहरण बनाए जा सकते हैं, और इस प्रकार, आपके ढांचे के सभी मूल्यों पर पूर्ण नियंत्रण होता है।
यह क्यों काम नहीं करेगा, अगर हम रूट प्रकार पैकेज-निजी बनाते हैं? –
हां, लेकिन यह इस प्रकार को देखने के लिए अवांछित ग्राहक है। हमें कारखाने के तरीकों के माध्यम से विनिर्देश की आवश्यकता है और अनुसूची वस्तुओं के लिए कारखाने के तरीकों के माध्यम से इसे पारित करना है। –