class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}
ఈ అంతర్గత తరగతులను నెస్టెడ్ అంటారు. అవి 2 రకాలుగా విభజించబడ్డాయి:
- నాన్-స్టాటిక్ నెస్టెడ్ తరగతులు. వీటిని అంతర్గత తరగతులు అని కూడా అంటారు.
- స్టాటిక్ నెస్టెడ్ తరగతులు.
- ఒక స్థానిక తరగతి
- ఒక అనామక తరగతి
public class Bicycle {
private String model;
private int weight;
public Bicycle(String model, int weight) {
this.model = model;
this.weight = weight;
}
public void start() {
System.out.println("Let's go!");
}
public class Handlebar {
public void right() {
System.out.println("Steer right!");
}
public void left() {
System.out.println("Steer left!");
}
}
public class Seat {
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
}
ఇక్కడ మాకు Bicycle
తరగతి ఉంది. ఇది 2 ఫీల్డ్లు మరియు 1 పద్ధతిని కలిగి ఉంది: start()
. ఇది సాధారణ తరగతికి భిన్నంగా ఉంటుంది, దీనిలో రెండు తరగతులు ఉంటాయి: Handlebar
మరియు Seat
. వారి కోడ్ తరగతి లోపల వ్రాయబడింది Bicycle
. ఇవి పూర్తి స్థాయి తరగతులు: మీరు చూడగలిగినట్లుగా, వాటిలో ప్రతి దాని స్వంత పద్ధతులు ఉన్నాయి. ఈ సమయంలో, మీకు ఒక ప్రశ్న ఉండవచ్చు: ప్రపంచంలో మనం ఒక తరగతిని మరొక తరగతిలో ఎందుకు ఉంచుతాము? వారిని అంతర్గత తరగతులుగా ఎందుకు తయారు చేస్తారు? సరే, మన ప్రోగ్రామ్లో హ్యాండిల్బార్ మరియు సీటు కాన్సెప్ట్ల కోసం మనకు ప్రత్యేక తరగతులు అవసరమని అనుకుందాం. అయితే, వాటిని గూడు కట్టుకోవడం మనకు అనవసరం! మేము సాధారణ తరగతులు చేయవచ్చు. ఉదాహరణకు, ఇలా:
public class Handlebar {
public void right() {
System.out.println("Steer right!");
}
public void left() {
System.out.println("Steer left");
}
}
public class Seat {
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
చాలా మంచి ప్రశ్న! వాస్తవానికి, మేము సాంకేతికత ద్వారా పరిమితం కాలేదు. అలా చేయడం ఖచ్చితంగా ఒక ఎంపిక. ఇక్కడ, ముఖ్యమైన విషయం ఏమిటంటే నిర్దిష్ట ప్రోగ్రామ్ మరియు దాని ప్రయోజనం యొక్క కోణం నుండి తరగతుల సరైన రూపకల్పన. అంతర్గత తరగతులు అనేది మరొక ఎంటిటీతో విడదీయరాని విధంగా అనుసంధానించబడిన ఒక ఎంటిటీని వేరు చేయడానికి. హ్యాండిల్బార్లు, సీట్లు మరియు పెడల్స్ సైకిల్లోని భాగాలు. సైకిల్ వేరు, అవి పెద్దగా అర్ధం కావు. మేము ఈ కాన్సెప్ట్లన్నింటినీ ప్రత్యేక పబ్లిక్ క్లాస్లుగా మార్చినట్లయితే, మా ప్రోగ్రామ్లో ఇలాంటి కోడ్ ఉండేదేమో:
public class Main {
public static void main(String[] args) {
Handlebar handlebar = new Handlebar();
handlebar.right();
}
}
అయ్యో... ఈ కోడ్ అర్థాన్ని వివరించడం కూడా కష్టం. మా వద్ద కొంత అస్పష్టమైన హ్యాండిల్బార్ ఉంది (ఇది ఎందుకు అవసరం? ఆలోచన లేదు, నిజం చెప్పాలంటే). మరియు ఈ హ్యాండిల్ కుడివైపుకు తిరుగుతుంది... అన్నింటికీ, సైకిల్ లేకుండా... కొన్ని కారణాల వల్ల. సైకిల్ కాన్సెప్ట్ నుండి హ్యాండిల్బార్ కాన్సెప్ట్ను వేరు చేయడం ద్వారా, మేము మా ప్రోగ్రామ్లో కొంత లాజిక్ను కోల్పోయాము. అంతర్గత తరగతిని ఉపయోగించి, కోడ్ చాలా భిన్నంగా కనిపిస్తుంది:
public class Main {
public static void main(String[] args) {
Bicycle peugeot = new Bicycle("Peugeot", 120);
Bicycle.Handlebar handlebar = peugeot.new Handlebar();
Bicycle.Seat seat = peugeot.new Seat();
seat.up();
peugeot.start();
handlebar.left();
handlebar.right();
}
}
కన్సోల్ అవుట్పుట్:
Seat up!
Let's go!
Steer left!
Steer right!
ఇప్పుడు మనం చూస్తున్నది హఠాత్తుగా అర్ధమవుతుంది! :) మేము సైకిల్ వస్తువును సృష్టించాము. మేము రెండు సైకిల్ "సబ్జెక్ట్"లను సృష్టించాము — హ్యాండిల్ బార్ మరియు సీటు. మేము సౌకర్యం కోసం సీటును పెంచాము మరియు మేము బయలుదేరాము: అవసరమైన విధంగా పెడలింగ్ మరియు స్టీరింగ్! :) మనకు అవసరమైన పద్ధతులు తగిన వస్తువులపై పిలువబడతాయి. ఇది అన్ని సాధారణ మరియు అనుకూలమైనది. ఈ ఉదాహరణలో, హ్యాండిల్బార్ మరియు సీటును వేరు చేయడం ఎన్క్యాప్సులేషన్ను మెరుగుపరుస్తుంది (మేము సంబంధిత తరగతి లోపల సైకిల్ భాగాల గురించి డేటాను దాచిపెడతాము) మరియు మరింత వివరణాత్మక సంగ్రహణను రూపొందించడానికి అనుమతిస్తుంది. ఇప్పుడు వేరే పరిస్థితిని చూద్దాం. బైక్ల దుకాణం మరియు బైక్ల కోసం విడిభాగాలను అనుకరించే ప్రోగ్రామ్ను రూపొందించాలని అనుకుందాం. ఈ పరిస్థితిలో, మా మునుపటి పరిష్కారం పని చేయదు. ఒక బైక్ దుకాణంలో, సైకిల్ నుండి వేరు చేయబడినప్పుడు కూడా ప్రతి ఒక్క సైకిల్ భాగం అర్ధవంతంగా ఉంటుంది. ఉదాహరణకు, మాకు "పెడల్లను కస్టమర్కి అమ్మడం", "కొత్త సీటు కొనండి" మొదలైన పద్ధతులు అవసరం. ఇక్కడ అంతర్గత తరగతులను ఉపయోగించడం పొరపాటు - మా కొత్త ప్రోగ్రామ్లోని ప్రతి సైకిల్ భాగానికి దాని అర్థం ఉంటుంది. దాని స్వంతం: దీనిని సైకిల్ భావన నుండి వేరు చేయవచ్చు. మీరు అంతర్గత తరగతులను ఉపయోగించాలా లేదా అన్ని ఎంటిటీలను ప్రత్యేక తరగతులుగా నిర్వహించాలా అని మీరు ఆలోచిస్తున్నట్లయితే, ఇది ఖచ్చితంగా మీరు శ్రద్ధ వహించాల్సిన అవసరం ఉంది. ఆబ్జెక్ట్-ఓరియెంటెడ్ ప్రోగ్రామింగ్ మంచిది, ఇది వాస్తవ-ప్రపంచ ఎంటిటీలను మోడల్ చేయడం సులభం చేస్తుంది. అంతర్గత తరగతులను ఉపయోగించాలా వద్దా అని నిర్ణయించేటప్పుడు ఇది మీ మార్గదర్శక సూత్రం కావచ్చు. నిజమైన దుకాణంలో, విడి భాగాలు సైకిళ్ల నుండి వేరుగా ఉంటాయి - ఇది సరే. అంటే ప్రోగ్రాం డిజైన్ చేసేటప్పుడు కూడా ఓకే. సరే, మేము "తత్వశాస్త్రం"ని కనుగొన్నాము :) ఇప్పుడు అంతర్గత తరగతుల యొక్క ముఖ్యమైన "సాంకేతిక" లక్షణాలతో పరిచయం చేసుకుందాం. మీరు ఖచ్చితంగా గుర్తుంచుకోవలసిన మరియు అర్థం చేసుకోవలసినది ఇక్కడ ఉంది:
-
ఒక అంతర్గత తరగతి యొక్క వస్తువు బాహ్య తరగతి యొక్క వస్తువు లేకుండా ఉనికిలో ఉండదు.
ఇది అర్ధమే: అందుకే మేము మా ప్రోగ్రామ్లో
Seat
మరియుHandlebar
అంతర్గత తరగతులను రూపొందించాము — తద్వారా మేము అనాథ హ్యాండిల్బార్లు మరియు సీట్లతో ముగుస్తుంది.ఈ కోడ్ కంపైల్ చేయదు:
public static void main(String[] args) { Handlebar handlebar = new Handlebar(); }
దీని నుండి మరొక ముఖ్యమైన లక్షణం క్రింది విధంగా ఉంది:
-
అంతర్గత తరగతి యొక్క వస్తువు బాహ్య తరగతి యొక్క వేరియబుల్స్కు ప్రాప్యతను కలిగి ఉంటుంది.
int seatPostDiameter
ఉదాహరణకు, మన తరగతికి వేరియబుల్ (సీట్పోస్ట్ యొక్క వ్యాసాన్ని సూచించడం) జోడిద్దాంBicycle
.అప్పుడు లోపలి తరగతిలో, మేము సీటు లక్షణాలను ప్రదర్శించే పద్ధతిని
Seat
సృష్టించవచ్చు :displaySeatProperties()
public class Bicycle { private String model; private int weight; private int seatPostDiameter; public Bicycle(String model, int weight, int seatPostDiameter) { this.model = model; this.weight = weight; this.seatPostDiameter = seatPostDiameter; } public void start() { System.out.println("Let's go!"); } public class Seat { public void up() { System.out.println("Seat up!"); } public void down() { System.out.println("Seat down!"); } public void displaySeatProperties() { System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter); } } }
ఇప్పుడు మనం ఈ సమాచారాన్ని మా ప్రోగ్రామ్లో ప్రదర్శించవచ్చు:
public class Main { public static void main(String[] args) { Bicycle bicycle = new Bicycle("Peugeot", 120, 40); Bicycle.Seat seat = bicycle.new Seat(); seat.displaySeatProperties(); } }
కన్సోల్ అవుట్పుట్:
Seat properties: seatpost diameter = 40
గమనిక:కొత్త వేరియబుల్ అత్యంత కఠినమైన యాక్సెస్ మాడిఫైయర్ ( )తో ప్రకటించబడింది
private
. మరియు ఇప్పటికీ అంతర్గత తరగతికి ప్రాప్యత ఉంది! -
ఒక అంతర్గత తరగతి యొక్క వస్తువు బాహ్య తరగతి యొక్క స్థిర పద్ధతిలో సృష్టించబడదు.
అంతర్గత తరగతులు ఎలా నిర్వహించబడతాయో నిర్దిష్ట లక్షణాల ద్వారా ఇది వివరించబడింది. ఒక అంతర్గత తరగతి పారామీటర్లతో కన్స్ట్రక్టర్లను కలిగి ఉంటుంది లేదా డిఫాల్ట్ కన్స్ట్రక్టర్ను కలిగి ఉంటుంది. కానీ సంబంధం లేకుండా, మేము అంతర్గత తరగతి యొక్క వస్తువును సృష్టించినప్పుడు, బాహ్య తరగతి యొక్క వస్తువు యొక్క సూచన అదృశ్యంగా అంతర్గత తరగతి యొక్క సృష్టించబడిన వస్తువుకు పంపబడుతుంది. అన్నింటికంటే, అటువంటి వస్తువు సూచన యొక్క ఉనికి ఒక సంపూర్ణ అవసరం. లేకపోతే, మేము అంతర్గత తరగతికి చెందిన వస్తువులను సృష్టించలేము.
కానీ బయటి తరగతి యొక్క పద్ధతి స్థిరంగా ఉంటే, మనకు బాహ్య తరగతికి సంబంధించిన వస్తువు ఉండకపోవచ్చు! మరియు ఇది అంతర్గత తరగతి ఎలా పనిచేస్తుందనే తర్కాన్ని ఉల్లంఘిస్తుంది. ఈ పరిస్థితిలో, కంపైలర్ లోపాన్ని సృష్టిస్తుంది:
public static Seat createSeat() { // Bicycle.this cannot be referenced from a static context return new Seat(); }
-
అంతర్గత తరగతి స్టాటిక్ వేరియబుల్స్ మరియు పద్ధతులను కలిగి ఉండకూడదు.
తర్కం ఒకటే: స్టాటిక్ పద్ధతులు మరియు వేరియబుల్స్ ఉనికిలో ఉంటాయి మరియు ఒక వస్తువు లేనప్పుడు కూడా పిలవబడతాయి లేదా సూచించబడతాయి.
కానీ బయటి తరగతికి సంబంధించిన వస్తువు లేకుండా, మనకు అంతర్గత తరగతికి ప్రాప్యత ఉండదు.
స్పష్టమైన వైరుధ్యం! అందుకే స్టాటిక్ వేరియబుల్స్ మరియు మెథడ్స్ ఇన్నర్ క్లాస్లలో అనుమతించబడవు.
మీరు వాటిని సృష్టించడానికి ప్రయత్నిస్తే కంపైలర్ లోపాన్ని సృష్టిస్తుంది:
public class Bicycle { private int weight; public class Seat { // An inner class cannot have static declarations public static void displaySeatProperties() { System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter); } } }
-
అంతర్గత తరగతి యొక్క వస్తువును సృష్టించేటప్పుడు, దాని యాక్సెస్ మాడిఫైయర్ ముఖ్యమైనది.
ప్రామాణిక యాక్సెస్ మాడిఫైయర్లతో అంతర్గత తరగతిని గుర్తించవచ్చు:
public
,private
,protected
, మరియుpackage private
.ఈ విషయం ఎందుకు?
ఇది మన ప్రోగ్రామ్లో అంతర్గత తరగతికి సంబంధించిన సందర్భాలను ఎక్కడ సృష్టించవచ్చో ప్రభావితం చేస్తుంది.
మన
Seat
క్లాస్గా డిక్లేర్ చేయబడితే , మనం ఏ ఇతర తరగతిలోనైనా వస్తువులనుpublic
సృష్టించవచ్చు .Seat
బయటి తరగతికి చెందిన వస్తువు కూడా ఉండాలనేది మాత్రమే అవసరం.మార్గం ద్వారా, మేము ఇప్పటికే దీన్ని ఇక్కడ చేసాము:
public class Main { public static void main(String[] args) { Bicycle peugeot = new Bicycle("Peugeot", 120); Bicycle.Handlebar handlebar = peugeot.new Handlebar(); Bicycle.Seat seat = peugeot.new Seat(); seat.up(); peugeot.start(); handlebar.left(); handlebar.right(); } }
Handlebar
మేము తరగతి నుండి లోపలి తరగతికి సులభంగా యాక్సెస్ పొందాముMain
.మనం అంతర్గత తరగతిని గా ప్రకటిస్తే
private
, మనం బాహ్య తరగతి లోపల మాత్రమే వస్తువులను సృష్టించగలము.మేము ఇకపై
Seat
"బయట" వస్తువును సృష్టించలేము:private class Seat { // Methods } public class Main { public static void main(String[] args) { Bicycle bicycle = new Bicycle("Peugeot", 120, 40); // Bicycle.Seat has private access in Bicycle Bicycle.Seat seat = bicycle.new Seat(); } }
మీరు బహుశా ఇప్పటికే లాజిక్ అర్థం చేసుకున్నారు :)
-
అంతర్గత తరగతులకు యాక్సెస్ మాడిఫైయర్లు సాధారణ వేరియబుల్ల మాదిరిగానే పని చేస్తాయి.
మాడిఫైయర్
protected
ఒకే ప్యాకేజీలో ఉన్న సబ్క్లాస్లు మరియు తరగతుల్లోని ఇన్స్టాన్స్ వేరియబుల్కు యాక్సెస్ను అందిస్తుంది.protected
అంతర్గత తరగతులకు కూడా పని చేస్తుంది.protected
మేము అంతర్గత తరగతి వస్తువులను సృష్టించవచ్చు :- బయటి తరగతిలో;
- దాని ఉపవర్గాలలో;
- ఒకే ప్యాకేజీలో ఉన్న తరగతులలో.
అంతర్గత తరగతికి యాక్సెస్ మాడిఫైయర్ ( ) లేకుంటే
package private
, అంతర్గత తరగతి యొక్క వస్తువులు సృష్టించబడతాయి:- బయటి తరగతిలో;
- ఒకే ప్యాకేజీలో ఉన్న తరగతులలో.
మీకు చాలా కాలంగా మాడిఫైయర్లతో పరిచయం ఉంది, కాబట్టి ఇక్కడ సమస్యలు లేవు.
GO TO FULL VERSION