"मी तुम्हाला « ऍक्सेस मॉडिफायर्स » बद्दल सांगणार आहे . मी त्यांच्याबद्दल पूर्वी एकदा सांगितले होते, पण पुनरावृत्ती हा शिक्षणाचा आधारस्तंभ आहे."

तुम्ही तुमच्या वर्गाच्या पद्धती आणि व्हेरिएबल्समध्ये इतर वर्गांकडे असलेला प्रवेश (दृश्यता) नियंत्रित करू शकता. ऍक्सेस मॉडिफायर प्रश्नाचे उत्तर देतो "या पद्धतीत/व्हेरिएबलमध्ये कोण प्रवेश करू शकतो?". तुम्ही प्रत्येक पद्धत किंवा व्हेरिएबलसाठी फक्त एक सुधारक निर्दिष्ट करू शकता.

1) « सार्वजनिक » सुधारक.

पब्लिक मॉडिफायरसह चिन्हांकित व्हेरिएबल, पद्धत किंवा क्लास प्रोग्राममधील कोठूनही प्रवेश केला जाऊ शकतो. ही मोकळेपणाची सर्वोच्च पदवी आहे: कोणतेही निर्बंध नाहीत.

2) « खाजगी » सुधारक.

खाजगी मॉडिफायरने चिन्हांकित केलेले व्हेरिएबल, पद्धत किंवा क्लास फक्त त्या वर्गात प्रवेश केला जाऊ शकतो जिथे तो घोषित केला आहे. चिन्हांकित पद्धत किंवा चल इतर सर्व वर्गांपासून लपवलेले आहे. ही गोपनीयतेची सर्वोच्च पदवी आहे: केवळ तुमच्या वर्गाद्वारे प्रवेशयोग्य. अशा पद्धती वारशाने मिळत नाहीत आणि त्या अधिलिखित केल्या जाऊ शकत नाहीत. याव्यतिरिक्त, ते वंशज वर्गात प्रवेश करू शकत नाहीत.

3)  « डीफॉल्ट सुधारक».

जर व्हेरिएबल किंवा पद्धत कोणत्याही सुधारकाने चिन्हांकित केलेली नसेल, तर ती "डीफॉल्ट" सुधारकाने चिन्हांकित केली जाते. या सुधारकासह व्हेरिएबल्स आणि पद्धती ज्या पॅकेजमध्ये घोषित केल्या आहेत त्या सर्व वर्गांसाठी दृश्यमान आहेत आणि फक्त त्या वर्गांसाठी. या सुधारकाला " पॅकेज " किंवा " पॅकेज प्रायव्हेट " ऍक्सेस असेही म्हटले जाते , हे दर्शविते की व्हेरिएबल्स आणि पद्धतींचा प्रवेश क्लास असलेल्या संपूर्ण पॅकेजसाठी खुला आहे.

4) « संरक्षित » सुधारक.

प्रवेशाचा हा स्तर पॅकेजपेक्षा किंचित विस्तृत आहे . संरक्षित मॉडिफायरसह चिन्हांकित केलेले व्हेरिएबल, पद्धत किंवा वर्ग त्याच्या पॅकेजमधून (जसे की "पॅकेज") आणि सर्व वारसा मिळालेल्या वर्गांमधून प्रवेश केला जाऊ शकतो.

हे सारणी हे सर्व स्पष्ट करते:

दृश्यमानतेचा प्रकार कीवर्ड प्रवेश
तुमचा वर्ग तुमचे पॅकेज वंशज सर्व वर्ग
खाजगी खाजगी होय नाही नाही नाही
पॅकेज (मॉडिफायर नाही) होय होय नाही नाही
संरक्षित संरक्षित होय होय होय नाही
सार्वजनिक सार्वजनिक होय होय होय होय

हे टेबल सहज लक्षात ठेवण्याचा एक मार्ग आहे. कल्पना करा की तुम्ही इच्छापत्र लिहित आहात. तुम्ही तुमच्या सर्व गोष्टींची चार श्रेणींमध्ये विभागणी करत आहात. तुमच्या वस्तू कोण वापरतात?

ज्याला प्रवेश आहे सुधारक उदाहरण
फक्त  मी खाजगी वैयक्तिक जर्नल
कुटुंब (मॉडिफायर नाही) कौटुंबिक फोटो
कुटुंब आणि वारस संरक्षित कौटुंबिक इस्टेट
सगळे सार्वजनिक आठवणी

"हे खूप कल्पना करण्यासारखे आहे की एकाच पॅकेजमधील वर्ग एकाच कुटुंबाचा भाग आहेत."

"मी तुम्हाला ओव्हरराइडिंग पद्धतींबद्दल काही मनोरंजक बारकावे देखील सांगू इच्छितो."

1) अमूर्त पद्धतीची अव्यक्त अंमलबजावणी.

समजा तुमच्याकडे खालील कोड आहे:

कोड
class Cat
{
 public String getName()
 {
  return "Oscar";
 }
}

आणि तुम्ही टायगर क्लास तयार करण्याचा निर्णय घेतला जो या वर्गाचा वारसा घेतो आणि नवीन वर्गात इंटरफेस जोडतो

कोड
class Cat
{
 public String getName()
 {
   return "Oscar";
 }
}
interface HasName
{
 String getName();
 int getWeight();
}
class Tiger extends Cat implements HasName
{
 public int getWeight()
 {
  return 115;
 }

}

IntelliJ IDEA ने तुम्हाला अंमलात आणण्यासाठी सांगितलेल्या सर्व गहाळ पद्धती तुम्ही अंमलात आणल्यास, नंतर तुम्हाला बग शोधण्यात बराच वेळ घालवावा लागेल.

असे दिसून आले की टायगर वर्गाला Cat कडून मिळालेली getName पद्धत आहे, जी HasName इंटरफेससाठी getName पद्धतीची अंमलबजावणी म्हणून घेतली जाईल.

"मला त्याबद्दल काहीही भयंकर दिसत नाही."

"ते खूप वाईट नाही, चुका होण्याची शक्यता असते."

परंतु ते आणखी वाईट असू शकते:

कोड
interface HasWeight
{
 int getValue();
}
interface HasSize
{
 int getValue();
}
class Tiger extends Cat implements HasWeight, HasSize
{
 public int getValue()
 {
  return 115;
 }
}

हे दिसून येते की आपण नेहमी एकाधिक इंटरफेसमधून वारसा मिळवू शकत नाही. अधिक तंतोतंत, आपण त्यांना वारसा मिळवू शकता, परंतु आपण ते योग्यरित्या लागू करू शकत नाही. उदाहरण पहा. दोन्ही इंटरफेससाठी तुम्ही getValue() पद्धत लागू करणे आवश्यक आहे, परंतु ते काय परत करावे हे स्पष्ट नाही: वजन किंवा आकार? याला सामोरे जावे लागणे खूप अप्रिय आहे.

"मी सहमत आहे. तुम्हाला एक पद्धत अंमलात आणायची आहे, पण तुम्ही करू शकत नाही. तुम्हाला आधीपासूनच बेस क्लासमधून समान नावाची पद्धत वारसाहक्क मिळाली आहे. ती तुटलेली आहे."

"पण एक चांगली बातमी आहे."

2) दृश्यमानता वाढवणे. जेव्हा तुम्हाला प्रकार वारसा मिळतो, तेव्हा तुम्ही पद्धतीची दृश्यमानता विस्तृत करू शकता. हे असे दिसते:

जावा कोड वर्णन
class Cat
{
 protected String getName()
 {
  return "Oscar";
 }
}
class Tiger extends Cat
{
 public String getName()
 {
  return "Oscar Tiggerman";
 }
}
protectedआम्ही वरून पद्धतीची दृश्यमानता वाढवली आहे public.
कोड हे "कायदेशीर" का आहे
public static void main(String[] args)
{
 Cat cat = new Cat();
 cat.getName();
}
सर्व काही छान आहे. येथे आपल्याला हे देखील माहित नाही की दृश्यमानता वंशज वर्गात वाढविली गेली आहे.
public static void main(String[] args)
{
 Tiger tiger = new Tiger();
 tiger.getName();
}
येथे आम्ही ज्या पद्धतीची दृश्यमानता वाढवली आहे त्याला कॉल करतो.

हे शक्य नसल्यास, आम्ही नेहमी टायगरमध्ये एक पद्धत घोषित करू शकतो:
सार्वजनिक स्ट्रिंग getPublicName()
{
super.getName(); //संरक्षित पद्धतीवर कॉल करा
}

दुसऱ्या शब्दांत, आम्ही कोणत्याही सुरक्षा उल्लंघनाबद्दल बोलत नाही आहोत.

public static void main(String[] args)
{
 Cat catTiger = new Tiger();
 catTiger.getName();
}
जर बेस क्लास ( मांजर ) मधील पद्धत कॉल करण्यासाठी आवश्यक असलेल्या सर्व अटी पूर्ण झाल्या असतील तर वंशज प्रकार ( वाघ ) वर पद्धत कॉल करण्यासाठी ते नक्कीच समाधानी आहेत. कारण मेथड कॉलवरील बंधने कमजोर होती, मजबूत नव्हती.

"मला खात्री नाही की मला पूर्णपणे समजले आहे, परंतु मी लक्षात ठेवेन की हे शक्य आहे."

3) परतावा प्रकार संकुचित करणे.

ओव्हरराइड केलेल्या पद्धतीमध्ये, आम्ही रिटर्न प्रकार संकुचित संदर्भ प्रकारात बदलू शकतो.

जावा कोड वर्णन
class Cat
{
 public Cat parent;
 public Cat getMyParent()
 {
  return this.parent;
 }
 public void setMyParent(Cat cat)
 {
  this.parent = cat;
 }
}
class Tiger extends Cat
{
 public Tiger getMyParent()
 {
  return (Tiger) this.parent;
 }
}
आम्ही पद्धत ओव्हररॉड केली getMyParent, आणि आता ती Tigerऑब्जेक्ट परत करते.
कोड हे "कायदेशीर" का आहे
public static void main(String[] args)
{
 Cat parent = new Cat();

 Cat me = new Cat();
 me.setMyParent(parent);
 Cat myParent = me.getMyParent();
}
सर्व काही छान आहे. येथे आम्हाला हे देखील माहित नाही की getMyParent पद्धतीचा रिटर्न प्रकार वंशज वर्गात वाढविला गेला आहे.

"जुना कोड" कसे कार्य करते आणि कार्य करते.

public static void main(String[] args)
{
 Tiger parent = new Tiger();

 Tiger me = new Tiger();
 me.setMyParent(parent);
 Tiger myParent = me.getMyParent();
}
येथे आम्ही त्या पद्धतीला कॉल करतो ज्याचा रिटर्न प्रकार संकुचित केला गेला आहे.

हे शक्य नसल्यास, आम्ही नेहमी टायगरमध्ये एक पद्धत घोषित करू शकतो:
सार्वजनिक वाघ getMyTigerParent()
{
return (Tiger) this.parent;
}

दुसऱ्या शब्दांत, कोणतेही सुरक्षा उल्लंघन आणि/किंवा प्रकार कास्टिंग उल्लंघने नाहीत.

public static void main(String[] args)
{
 Tiger parent = new Tiger();

 Cat me = new Tiger();
 me.setMyParent(parent);
 Cat myParent = me.getMyParent();
}
आणि येथे सर्व काही ठीक चालले आहे, जरी आम्ही व्हेरिएबल्सचा प्रकार बेस क्लास (मांजर) पर्यंत विस्तृत केला.

ओव्हरराइड केल्यामुळे, योग्य setMyParent पद्धत म्हणतात.

आणि getMyParent मेथडला कॉल करताना काळजी करण्याची काहीच गरज नाही , कारण रिटर्न व्हॅल्यू, जरी टायगर क्लासचे असले तरी, कोणत्याही समस्यांशिवाय बेस क्लास (Cat) च्या myParent व्हेरिएबलला नियुक्त केले जाऊ शकते .

टायगर ऑब्जेक्ट्स टायगर व्हेरिएबल्स आणि कॅट व्हेरिएबल्समध्ये सुरक्षितपणे साठवल्या जाऊ शकतात.

"हो. समजले. पद्धती ओव्हरराइड करताना, जर आम्ही आमचे ऑब्जेक्ट्स फक्त बेस क्लास हाताळू शकणार्‍या आणि आमच्या वर्गाबद्दल काहीही माहिती नसलेल्या कोडमध्ये पास केले तर हे सर्व कसे कार्य करते याची तुम्हाला जाणीव असणे आवश्यक आहे. "

"नक्की! मग एक मोठा प्रश्न हा आहे की आपण पद्धती ओव्हरराइड करताना रिटर्न व्हॅल्यूचा प्रकार कमी का करू शकत नाही?"

"हे स्पष्ट आहे की या प्रकरणात बेस क्लासमधील कोड कार्य करणे थांबवेल:"

जावा कोड समस्येचे स्पष्टीकरण
class Cat
{
 public Cat parent;
 public Cat getMyParent()
 {
  return this.parent;
 }
 public void setMyParent(Cat cat)
 {
  this.parent = cat;
 }
}
class Tiger extends Cat
{
 public Object getMyParent()
 {
  if (this.parent != null)
   return this.parent;
  else
   return "I'm an orphan";
 }
}
आम्ही getMyParent पद्धत ओव्हरलोड केली आणि त्याच्या रिटर्न व्हॅल्यूचा प्रकार कमी केला.

इथे सर्व काही ठीक आहे.

public static void main(String[] args)
{
 Tiger parent = new Tiger();

 Cat me = new Tiger();
 Cat myParent = me.getMyParent();
}
मग हा कोड काम करणे थांबवेल.

getMyParent पद्धत ऑब्जेक्टची कोणतीही घटना परत करू शकते, कारण ती प्रत्यक्षात टायगर ऑब्जेक्टवर कॉल केली जाते.

आणि असाइनमेंटपूर्वी आमच्याकडे चेक नाही. अशा प्रकारे, हे पूर्णपणे शक्य आहे की Cat-प्रकार myParent व्हेरिएबल स्ट्रिंग संदर्भ संचयित करेल.

"अद्भुत उदाहरण, अमिगो!"

Java मध्ये, एखादी पद्धत कॉल करण्यापूर्वी, ऑब्जेक्टमध्ये अशी पद्धत आहे की नाही हे तपासले जात नाही. सर्व तपासण्या रनटाइमच्या वेळी होतात. आणि गहाळ पद्धतीला [काल्पनिक] कॉल केल्यामुळे बहुधा प्रोग्राम अस्तित्वात नसलेला बायकोड कार्यान्वित करण्याचा प्रयत्न करेल. यामुळे शेवटी एक घातक त्रुटी निर्माण होईल आणि ऑपरेटिंग सिस्टम जबरदस्तीने प्रोग्राम बंद करेल.

"अरे. आता मला कळले."