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