"నేను మీకు « యాక్సెస్ మాడిఫైయర్‌లు » గురించి చెప్పబోతున్నాను . వాటి గురించి నేను ఇంతకు ముందు ఒకసారి చెప్పాను, కానీ పునరావృతం అనేది నేర్చుకునే స్తంభం."

మీ తరగతి పద్ధతులు మరియు వేరియబుల్స్‌కు ఇతర తరగతులు కలిగి ఉండే యాక్సెస్ (విజిబిలిటీ)ని మీరు నియంత్రించవచ్చు. "ఈ పద్ధతి/వేరియబుల్‌ని ఎవరు యాక్సెస్ చేయగలరు?" అనే ప్రశ్నకు యాక్సెస్ మాడిఫైయర్ సమాధానమిస్తుంది. మీరు ప్రతి పద్ధతి లేదా వేరియబుల్ కోసం ఒక మాడిఫైయర్‌ను మాత్రమే పేర్కొనవచ్చు.

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 మీకు అమలు చేయమని చెప్పిన అన్ని తప్పిపోయిన పద్ధతులను అమలు చేస్తే, ఆ తర్వాత మీరు బగ్ కోసం చాలా కాలం వెతకవచ్చు.

టైగర్ క్లాస్ క్యాట్ నుండి వారసత్వంగా పొందబడిన 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();
}
అంతా బాగుంది. ఇక్కడ descendant క్లాస్‌లో getMyParent పద్ధతి యొక్క రిటర్న్ రకం విస్తరించబడిందని కూడా మనకు తెలియదు.

"పాత కోడ్" ఎలా పని చేస్తుంది మరియు పనిచేస్తుంది.

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

 Tiger me = new Tiger();
 me.setMyParent(parent);
 Tiger myParent = me.getMyParent();
}
ఇక్కడ మేము రిటర్న్ రకం ఇరుకైన పద్ధతిని పిలుస్తాము.

ఇది సాధ్యం కాకపోతే, మేము ఎల్లప్పుడూ టైగర్‌లో ఒక పద్ధతిని ప్రకటించవచ్చు:
public Tiger 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 పద్ధతికి కాల్ చేస్తున్నప్పుడు చింతించాల్సిన పని లేదు , ఎందుకంటే టైగర్ క్లాస్‌కు సంబంధించిన రిటర్న్ విలువ ఇప్పటికీ ఎటువంటి సమస్యలు లేకుండా బేస్ క్లాస్ (క్యాట్) యొక్క 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 పద్ధతి ఆబ్జెక్ట్ యొక్క ఏదైనా ఉదాహరణను తిరిగి ఇవ్వగలదు, ఎందుకంటే ఇది నిజానికి టైగర్ వస్తువుపై పిలువబడుతుంది.

మరియు అసైన్‌మెంట్‌కు ముందు మా వద్ద చెక్ లేదు. అందువల్ల, క్యాట్-టైప్ myParent వేరియబుల్ స్ట్రింగ్ రిఫరెన్స్‌ను నిల్వ చేయడం పూర్తిగా సాధ్యమే .

"అద్భుతమైన ఉదాహరణ, అమిగో!"

జావాలో, ఒక పద్ధతిని పిలవడానికి ముందు, వస్తువుకు అలాంటి పద్ధతి ఉందో లేదో తనిఖీ చేయడం లేదు. అన్ని తనిఖీలు రన్‌టైమ్‌లో జరుగుతాయి. మరియు తప్పిపోయిన పద్ధతికి [ఊహాత్మక] కాల్ చాలా మటుకు ప్రోగ్రామ్ ఉనికిలో లేని బైట్‌కోడ్‌ని అమలు చేయడానికి ప్రయత్నించేలా చేస్తుంది. ఇది చివరికి ప్రాణాంతకమైన లోపానికి దారి తీస్తుంది మరియు ఆపరేటింగ్ సిస్టమ్ ప్రోగ్రామ్‌ను బలవంతంగా మూసివేస్తుంది.

"ఓహో. ఇప్పుడు తెలిసింది."