ওহে! অতীতের একটি পাঠে, আমরা আদিম প্রকারের ঢালাই নিয়ে আলোচনা করেছি। আসুন সংক্ষেপে কি আলোচনা করা হয়েছিল তা স্মরণ করি। আমরা আদিম প্রকারগুলিকে কল্পনা করেছি (এই ক্ষেত্রে, সংখ্যাসূচক প্রকারগুলি) নেস্টিং পুতুল হিসাবে যেগুলি তাদের দখলকৃত স্মৃতির পরিমাণ অনুসারে আকারে পরিবর্তিত হয়। আপনি মনে রাখবেন, একটি বড় পুতুলের ভিতরে একটি ছোট পুতুল রাখা বাস্তব জীবনে এবং জাভা প্রোগ্রামিং উভয় ক্ষেত্রেই সহজ।
public class Main {
public static void main(String[] args) {
int bigNumber = 10000000;
short smallNumber = (short) bigNumber;
System.out.println(smallNumber);
}
}
এটি স্বয়ংক্রিয় রূপান্তর বা প্রশস্তকরণের একটি উদাহরণ । এটি নিজেই ঘটে, তাই আপনাকে অতিরিক্ত কোড লিখতে হবে না। শেষ পর্যন্ত, আমরা অস্বাভাবিক কিছু করছি না: আমরা কেবল একটি ছোট পুতুলকে একটি বড় পুতুলে রাখছি। এটি অন্য বিষয় যদি আমরা বিপরীত করার চেষ্টা করি এবং একটি বড় রাশিয়ান পুতুলকে একটি ছোট পুতুলে রাখি। আপনি বাস্তব জীবনে এটি করতে পারবেন না, কিন্তু প্রোগ্রামিং আপনি করতে পারেন। কিন্তু একটি nuance আছে. int
আমরা একটি পরিবর্তনশীল মধ্যে একটি স্থাপন করার চেষ্টা করলে short
, জিনিস আমাদের জন্য এত সহজে যেতে না. সব পরে, short
ভেরিয়েবল শুধুমাত্র 16 বিট তথ্য ধারণ করে, কিন্তু একটি int
32 বিট দখল করে! ফলস্বরূপ, পাস করা মান বিকৃত হয়। কম্পাইলার আমাদের একটি ত্রুটি দেবে (' দোস্ত, আপনি সন্দেহজনক কিছু করছেন!')। কিন্তু যদি আমরা স্পষ্টভাবে নির্দেশ করি যে আমরা আমাদের মানকে রূপান্তর করছি, এটি এগিয়ে যাবে এবং অপারেশনটি করবে।
public class Main {
public static void main(String[] args) {
int bigNumber = 10000000;
bigNumber = (short) bigNumber;
System.out.println(bigNumber);
}
}
যে আমরা উপরের উদাহরণে কি শুধু. অপারেশনটি সঞ্চালিত হয়েছিল, কিন্তু যেহেতু short
ভেরিয়েবলটি 32 বাইটের মধ্যে শুধুমাত্র 16টি মিটমাট করতে পারে, চূড়ান্ত মানটি বিকৃত হয় এবং আমরা -27008 নম্বরটি পাই । এই ধরনের একটি অপারেশন একটি স্পষ্ট রূপান্তর বলা হয়, বা সংকীর্ণ .
রেফারেন্স প্রকারের প্রশস্তকরণ এবং সংকীর্ণ করার উদাহরণ
এখন আসুন একই অপারেটর সম্পর্কে কথা বলি যা আদিম প্রকারের ক্ষেত্রে নয়, বস্তু এবং রেফারেন্স ভেরিয়েবলের ক্ষেত্রে প্রয়োগ করা হয় ! এই জাভা কিভাবে কাজ করে? এটা আসলে বেশ সহজ. এমন বস্তু আছে যা সম্পর্কহীন। এটা অনুমান করা যৌক্তিক হবে যে তারা একে অপরে রূপান্তরিত হতে পারে না, স্পষ্টভাবে বা স্বয়ংক্রিয়ভাবে নয়:
public class Cat {
}
public class Dog {
}
public class Main {
public static void main(String[] args) {
Cat cat = new Dog(); // Error!
}
}
এখানে, অবশ্যই, আমরা একটি ত্রুটি পেতে. এবং ক্লাস একে অপরের সাথে সম্পর্কিত নয়, এবং আমরা একটি থেকে Cat
অন্যটিতে Dog
যাওয়ার জন্য একটি 'কনভার্টার' লিখিনি। এটা বোঝায় যে আমরা এটি করতে পারি না: কম্পাইলারের কোন ধারণা নেই কিভাবে এই বস্তুগুলিকে এক প্রকার থেকে অন্য টাইপ রূপান্তর করা যায়। যদি বস্তুগুলি সম্পর্কিত হয়, ভাল, এটি অন্য বিষয়! কিভাবে সম্পর্কিত? সর্বোপরি, উত্তরাধিকারের মাধ্যমে। আসুন ক্লাসের একটি ছোট সিস্টেম তৈরি করতে উত্তরাধিকার ব্যবহার করার চেষ্টা করি। প্রাণীদের প্রতিনিধিত্ব করার জন্য আমাদের একটি সাধারণ শ্রেণী থাকবে:
public class Animal {
public void introduce() {
System.out.println("I'm Animal");
}
}
সবাই জানে যে প্রাণী গৃহপালিত (পোষা প্রাণী) বা বন্য হতে পারে:
public class WildAnimal extends Animal {
public void introduce() {
System.out.println("I'm WildAnimal");
}
}
public class Pet extends Animal {
public void introduce() {
System.out.println("I'm Pet");
}
}
উদাহরণস্বরূপ, ক্যানাইনগুলি নিন — আমাদের গৃহপালিত কুকুর এবং কোয়োট রয়েছে:
public class Dog extends Pet {
public void introduce() {
System.out.println("I'm Dog");
}
}
public class Coyote extends WildAnimal {
public void introduce() {
System.out.println ("I'm Coyote");
}
}
আমরা বিশেষভাবে সবচেয়ে মৌলিক ক্লাস বেছে নিয়েছি যাতে সেগুলি বোঝা সহজ হয়। আমাদের সত্যিই কোন ক্ষেত্র প্রয়োজন নেই, এবং একটি পদ্ধতি যথেষ্ট। আসুন এই কোডটি কার্যকর করার চেষ্টা করি:
public class Main {
public static void main(String[] args) {
Animal animal = new Pet();
animal.introduce();
}
}
আপনি কি মনে করেন কনসোলে প্রদর্শিত হবে? introduce
ক্লাসের পদ্ধতি বা Pet
ক্লাস Animal
আহ্বান করা হবে? আপনি পড়া চালিয়ে যাওয়ার আগে আপনার উত্তর ন্যায্যতা করার চেষ্টা করুন. এবং এখানে ফলাফল! আমি পোষ্য কেন আমরা এটা পেয়েছিলাম? এটা সব সহজ. আমাদের একটি প্যারেন্ট ভেরিয়েবল এবং একটি ডিসেন্ডেন্ট অবজেক্ট আছে। লিখিত ভাবে,
Animal animal = new Pet();
আমরা একটি Pet
রেফারেন্স প্রশস্ত করেছি এবং এটি একটি Animal
ভেরিয়েবলে বরাদ্দ করেছি। আদিম প্রকারের মতো, রেফারেন্স প্রকারগুলি জাভাতে স্বয়ংক্রিয়ভাবে প্রসারিত হয়। এটি ঘটতে আপনাকে অতিরিক্ত কোড লিখতে হবে না। এখন আমাদের কাছে একটি বংশধর বস্তু রয়েছে যা একটি পিতামাতার রেফারেন্সে বরাদ্দ করা হয়েছে। ফলস্বরূপ, আমরা দেখতে পাই যে পদ্ধতি কলটি বংশধর শ্রেণীর উপর করা হয়েছে। আপনি যদি এখনও পুরোপুরি বুঝতে না পারেন কেন এই কোডটি কাজ করে, তাহলে এটিকে সরল ভাষায় লিখুন:
Animal animal = new DomesticatedAnimal();
এর সাথে কোন সমস্যা নেই, তাই না? কল্পনা করুন যে এটি বাস্তব জীবন, এবং রেফারেন্সটি কেবল একটি কাগজের লেবেল যার উপর 'প্রাণী' লেখা। আপনি যদি সেই কাগজের টুকরোটি নিয়ে যে কোনও পোষা প্রাণীর কলারে এটি সংযুক্ত করেন তবে সবকিছু ঠিক হয়ে যাবে। সব পরে, যে কোন পোষা প্রাণী! বিপরীত প্রক্রিয়া — উত্তরাধিকার গাছ থেকে উত্তরাধিকারসূত্রে চলে যাওয়া — সংকীর্ণ হচ্ছে:
public class Main {
public static void main(String[] args) {
WildAnimal wildAnimal = new Coyote();
Coyote coyote = (Coyote) wildAnimal;
coyote.introduce();
}
}
আপনি দেখতে পাচ্ছেন, এখানে আমরা স্পষ্টভাবে সেই ক্লাসটি নির্দেশ করি যেটি আমরা আমাদের অবজেক্টে রূপান্তর করতে চাই। আমরা আগে একটি WildAnimal
পরিবর্তনশীল ছিল, এবং এখন আমরা একটি আছে Coyote
, যা উত্তরাধিকার গাছে কম। এটা বোঝায় যে একটি সুস্পষ্ট ইঙ্গিত ছাড়া কম্পাইলার এই ধরনের একটি অপারেশন অনুমতি দেবে না, কিন্তু যদি আমরা বন্ধনীর ধরন নির্দেশ করি, তাহলে সবকিছু কাজ করে। আরেকটি আকর্ষণীয় উদাহরণ বিবেচনা করুন:
public class Main {
public static void main(String[] args) {
Pet pet = new Animal(); // Error!
}
}
কম্পাইলার একটি ত্রুটি তৈরি করে! কিন্তু কেন? কারণ আপনি একটি বংশধর রেফারেন্সে একটি মূল বস্তু বরাদ্দ করার চেষ্টা করছেন। অন্য কথায়, আপনি এরকম কিছু করার চেষ্টা করছেন:
DomesticatedAnimal domesticatedAnimal = new Animal();
আচ্ছা, হয়তো সবকিছু কাজ করবে যদি আমরা স্পষ্টভাবে উল্লেখ করি যে আমরা রূপান্তর করার চেষ্টা করছি? এটি সংখ্যার সাথে কাজ করেছে — আসুন একবার চেষ্টা করে দেখি! :)
public class Main {
public static void main(String[] args) {
Pet pet = (Pet) new Animal();
}
}
"প্রধান" থ্রেডে ব্যতিক্রম java.lang.ClassCastException: প্রাণীকে পোষা ত্রুটির জন্য কাস্ট করা যাবে না! কম্পাইলার এই সময়ে আমাদের চিৎকার করেনি, কিন্তু আমরা একটি ব্যতিক্রম দিয়ে শেষ করেছি। আমরা ইতিমধ্যেই কারণটি জানি: আমরা একটি বংশধর রেফারেন্সে একটি মূল বস্তু বরাদ্দ করার চেষ্টা করছি৷ কিন্তু কেন আপনি ঠিক তা করতে পারেন না? কারণ সব প্রাণীই গৃহপালিত প্রাণী নয়। আপনি একটি Animal
বস্তু তৈরি করেছেন এবং এটি একটি ভেরিয়েবলে বরাদ্দ করার চেষ্টা করছেন Pet
। একটি কোয়োটও একটি Animal
, তবে এটি একটি নয় Pet
। অন্য কথায়, আপনি যখন লেখেন
Pet pet = (Pet) new Animal();
new Animal()
কোন প্রাণীর প্রতিনিধিত্ব করতে পারে, অগত্যা একটি পোষা নয়! স্বাভাবিকভাবেই, আপনার Pet pet
ভেরিয়েবল শুধুমাত্র পোষা প্রাণী (এবং তাদের বংশধরদের) সংরক্ষণের জন্য উপযুক্ত এবং কোন ধরনের প্রাণী নয়। এই কারণেই একটি বিশেষ জাভা ব্যতিক্রম, ClassCastException
, এমন ক্ষেত্রে তৈরি করা হয়েছে যেখানে ক্লাস কাস্ট করার সময় একটি ত্রুটি ঘটে। বিষয়গুলি পরিষ্কার করতে এর আবার পর্যালোচনা করা যাক। একটি অভিভাবক রেফারেন্স একটি বংশধর শ্রেণীর উদাহরণ নির্দেশ করতে পারে:
public class Main {
public static void main(String[] args) {
Pet pet = new Pet();
Animal animal = pet;
Pet pet2 = (Pet) animal;
pet2.introduce();
}
}
উদাহরণস্বরূপ, এখানে আমাদের কোন সমস্যা নেই। আমরা Pet
একটি ভেরিয়েবল দ্বারা উল্লেখ করা একটি বস্তু আছে Pet
. পরে, একটি Animal
রেফারেন্স একই বস্তুর দিকে নির্দেশ করে। এর পরে, আমরা animal
একটি তে রূপান্তরিত করি Pet
। উপায় দ্বারা, কেন যে আমাদের জন্য কাজ? গতবার আমরা ব্যতিক্রম পেয়েছি! কারণ এবার আমাদের মূল বস্তুটি একটি Pet
!
Pet pet = new Pet();
কিন্তু শেষ উদাহরণে, এটি একটি Animal
বস্তু ছিল:
Pet pet = (Pet) new Animal();
আপনি একটি বংশধর ভেরিয়েবলে একটি পূর্বপুরুষ বস্তু বরাদ্দ করতে পারবেন না। আপনি বিপরীত করতে পারেন.
GO TO FULL VERSION