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("Go!");
}
public class HandleBar {
public void right() {
System.out.println("Steering wheel to the right!");
}
public void left() {
System.out.println("Steering wheel to the left!");
}
}
public class Seat {
public void up() {
System.out.println("The seat is up!");
}
public void down() {
System.out.println("The seat is down!");
}
}
}
یہاں ہمارے پاس ایک کلاس ہے Bicycle
- سائیکل۔ اس میں 2 فیلڈز اور 1 طریقہ ہے start()
۔ ریگولر کلاس سے اس کا فرق یہ ہے کہ اس کی دو کلاسیں ہیں، جن کا کوڈ اندر لکھا ہوا ہے Bicycle
- یہ کلاسز HandleBar
(سٹیرنگ وہیل) اور Seat
(سیٹ) ہیں۔ یہ مکمل کلاسز ہیں: جیسا کہ آپ دیکھ سکتے ہیں، ان میں سے ہر ایک کے اپنے طریقے ہیں۔ اس موقع پر، آپ کے ذہن میں ایک سوال ہو سکتا ہے: ہم نے ایک کلاس کو دوسرے میں کیوں ڈالا؟ ان کو اندرونی کیوں بناتے ہیں؟ ٹھیک ہے، ہم کہتے ہیں کہ ہمیں پروگرام میں اسٹیئرنگ وہیل اور سیٹ کے لیے الگ الگ کلاسز کی ضرورت ہے۔ لیکن آپ کو انہیں گھونسلہ بنانے کی ضرورت نہیں ہے! آپ باقاعدہ کلاسز بھی کر سکتے ہیں۔ مثال کے طور پر، اس طرح:
public class HandleBar {
public void right() {
System.out.println("Steering wheel to the right!");
}
public void left() {
System.out.println("Steering wheel left");
}
}
public class Seat {
public void up() {
System.out.println("The seat is up!");
}
public void down() {
System.out.println("The seat is 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
داخلیHandleBar
کلاسز بنا دی ہیں، تاکہ ہمارے پروگرام میں بغیر مالک کے اسٹیئرنگ وہیل اور سیٹیں نظر نہ آئیں۔یہ کوڈ مرتب نہیں کرے گا:
public static void main(String[] args) { HandleBar handleBar = new HandleBar(); }
اس سے درج ذیل اہم خصوصیت سامنے آتی ہے:
-
اندرونی طبقے کی کسی چیز کو "بیرونی" کلاس کے متغیرات تک رسائی حاصل ہوتی ہے۔
مثال کے طور پر، آئیے اپنی کلاس میں
Bicycle
ایک متغیر شامل کریںint seatPostDiameter
- سیٹ پوسٹ کا قطر۔پھر اندرونی کلاس میں
Seat
ہم ایک طریقہ بنا سکتے ہیںgetSeatParam()
جو ہمیں سیٹ پیرامیٹر بتائے گا: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("Go!"); } public class Seat { public void up() { System.out.println("The seat is up!"); } public void down() { System.out.println("The seat is down!"); } public void getSeatParam() { System.out.println("Seat parameter: 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.getSeatParam(); } }
کنسول آؤٹ پٹ:
Параметр сиденья: диаметр подседельного штыря = 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 { //inner class cannot have static declarations public static void getSeatParam() { System.out.println("Seat parameter: seatpost diameter = " + Bicycle.this.seatPostDiameter); } } }
-
اندرونی طبقے کی کوئی چیز بناتے وقت، اس تک رسائی میں ترمیم کرنے والا ایک اہم کردار ادا کرتا ہے۔
ایک اندرونی طبقے کو معیاری رسائی میں ترمیم کرنے والے -
public
, اور .private
protected
package private
یہ کیوں ضروری ہے؟
یہ اس بات پر اثر انداز ہوتا ہے کہ ہمارے پروگرام میں ہم اندرونی طبقے کو کہاں سے شروع کر سکتے ہیں۔
اگر ہماری کلاس کو
Seat
قرار دیا جاتا ہے توpublic
ہم اس کی اشیاء کو کسی دوسری کلاس میں بنا سکتے ہیں۔ ضرورت صرف یہ ہے کہ "بیرونی" طبقے کی کوئی چیز بھی موجود ہو۔ویسے، ہم پہلے ہی یہاں کر چکے ہیں:
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 a private access in 'Bicycle' Bicycle.Seat seat = bicycle.new Seat(); } }
آپ شاید پہلے ہی منطق کو سمجھ چکے ہوں :)
-
اندرونی کلاسوں کے لیے رسائی میں ترمیم کرنے والے وہی کام کرتے ہیں جیسا کہ باقاعدہ متغیرات کے لیے۔
ترمیم کنندہ
protected
کلاس متغیر تک اپنی نسلی کلاسوں اور کلاسوں میں رسائی فراہم کرتا ہے جو ایک ہی پیکیج میں ہیں۔protected
اندرونی طبقات کے لیے بھی یہی کام کرتا ہے۔protected
اندرونی طبقے کی اشیاء بنائی جا سکتی ہیں:- "بیرونی" کلاس کے اندر؛
- اس کی نسلی کلاسوں میں؛
- ان کلاسوں میں جو ایک ہی پیکیج میں ہیں۔
اگر اندرونی طبقے میں رسائی موڈیفائر (
package private
) نہیں ہے تو اندرونی کلاس کی اشیاء بنائی جا سکتی ہیں۔- "بیرونی" کلاس کے اندر؛
- ان کلاسوں میں جو ایک ہی پیکیج میں ہیں۔
آپ ایک طویل عرصے سے ترمیم کرنے والوں سے واقف ہیں، لہذا یہاں کوئی مسئلہ نہیں ہوگا۔
GO TO FULL VERSION