JavaRush /جاوا بلاگ /Random-UR /جاوا میں حتمی، مستقل اور ناقابل تغیر

جاوا میں حتمی، مستقل اور ناقابل تغیر

گروپ میں شائع ہوا۔
ہیلو! لفظ "موڈیفائر" آپ کے لیے پہلے سے ہی واقف ہے۔ کم از کم، آپ کو رسائی میں ترمیم کرنے والے (عوامی، نجی) اور جامد ترمیم کار کا سامنا کرنا پڑا ہے۔ آج ہم اسپیشل فائنل موڈیفائر کے بارے میں بات کریں گے ۔ اسے ہمارے پروگرام کے ان شعبوں کو "سیمنٹ" کرنے کے لیے کہا جا سکتا ہے جہاں ہمیں مستقل، غیر مبہم، غیر تبدیل شدہ رویے کی ضرورت ہے۔ اسے ہمارے پروگرام کے تین شعبوں میں استعمال کیا جا سکتا ہے: کلاسز، طریقے اور متغیر۔ جاوا میں ناقابل تغیر: حتمی، مستقل اور ناقابل تغیر - 2 آئیے ایک ایک کرکے ان کے ذریعے چلتے ہیں۔ اگر کسی کلاس ڈیکلریشن میں فائنل موڈیفائر ہوتا ہے تو اس کا مطلب ہے کہ آپ اس کلاس سے وراثت نہیں پا سکتے۔ پچھلے لیکچرز میں، ہم نے وراثت کی ایک سادہ سی مثال دیکھی: ہمارے پاس والدین کی کلاس تھی Animal، اور دو بچوں کی کلاسیں - CatاورDog
public class Animal {
}

public class Cat extends Animal {
   //..поля и методы класса Cat
}

public class Dog extends Animal {

   //..поля и методы класса Dog
}
تاہم، اگر ہم کلاس کے لیے Animalایک ترمیم کنندہ کی وضاحت کرتے ہیں، تو کلاسیں اس سے بھی finalوراثت حاصل نہیں کر سکیں گی ۔ CatDog
public final class Animal {

}

public class Cat extends Animal {

   //ошибка! Cannot inherit from final Animal
}
مرتب کرنے والا فوری طور پر ایک غلطی پیدا کرتا ہے۔ جاوا میں پہلے سے ہی بہت سی کلاسیں نافذ ہیں final۔ ان میں سب سے مشہور ہے جو آپ مسلسل استعمال کرتے ہیں String۔ مزید برآں، اگر کسی کلاس کو قرار دیا جائے تو finalاس کے تمام طریقے بھی بن جاتے ہیں final۔ اس کا کیا مطلب ہے؟ اگر کسی طریقہ کے لیے ترمیم کنندہ کی وضاحت کی گئی ہے finalتو اس طریقہ کو اوور رائڈ نہیں کیا جا سکتا۔ مثال کے طور پر، ہمارے پاس ایک کلاس ہے Animalجو ایک طریقہ کی وضاحت کرتی ہے voice()۔ تاہم، کتے اور بلیاں واضح طور پر مختلف طریقے سے "باتیں" کرتے ہیں۔ لہذا، ہر ایک کلاس میں - Catاور Dog- ہم ایک طریقہ بنائیں گے voice()، لیکن ہم اسے مختلف طریقے سے نافذ کریں گے۔
public class Animal {

   public void voice() {
       System.out.println("Voice!");
   }
}

public class Cat extends Animal {

   @Override
   public void voice() {
       System.out.println("Meow!");
   }
}

public class Dog extends Animal {

   @Override
   public void voice() {
       System.out.println("Woof!");
   }
}
کلاسوں میں Catاور Dogہم نے پیرنٹ کلاس کے طریقہ کار کو اوور رائیڈ کر دیا ہے۔ اب جانور آواز دے گا اس پر منحصر ہے کہ یہ کس کلاس کا اعتراض ہے:
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       Dog dog = new Dog();

       cat.voice();
       dog.voice();
   }
}
نتیجہ: میانو! ووف! تاہم، اگر Animalہم کسی کلاس میں کسی طریقہ کا اعلان کرتے ہیں voice()تو final، دوسری کلاسوں میں اس کی دوبارہ وضاحت ممکن نہیں ہوگی:
public class Animal {

   public final void voice() {
       System.out.println("Voice!");
   }
}


public class Cat extends Animal {

   @Override
   public void voice() {//ошибка! final-метод не может быть переопределен!
       System.out.println("Meow!");
   }
}
پھر ہماری اشیاء کو طریقہ استعمال کرنے پر مجبور کیا جائے گا voice()جیسا کہ اس کی پیرنٹ کلاس میں تعریف کی گئی ہے:
public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   cat.voice();
   dog.voice();
}
نتیجہ: آواز! آواز! اب finalمتغیرات کے بارے میں۔ بصورت دیگر انہیں مستقل کہا جاتا ہے ۔ سب سے پہلے (اور سب سے اہم بات)، ایک مستقل کو تفویض کردہ پہلی قدر کو تبدیل نہیں کیا جا سکتا۔ یہ ایک بار اور ہمیشہ کے لئے تفویض کیا جاتا ہے۔
public class Main {

   private static final int CONSTANT_EXAMPLE = 333;

   public static void main(String[] args) {

       CONSTANT_EXAMPLE = 999;//ошибка! Нельзя присвоить новое meaning final-переменной!
   }
}
مستقل کو فوری طور پر شروع کرنے کی ضرورت نہیں ہے۔ یہ بعد میں کیا جا سکتا ہے۔ لیکن پہلے تفویض کردہ قدر ہمیشہ کے لیے رہے گی۔
public static void main(String[] args) {

   final int CONSTANT_EXAMPLE;

   CONSTANT_EXAMPLE = 999;//так делать можно
}
دوم، ہمارے متغیر کے نام پر توجہ دیں۔ جاوا کانسٹینٹ کا نام دینے کا کنونشن مختلف ہے۔ یہ اونٹ کیس نہیں ہے جس کے ہم عادی ہیں۔ باقاعدہ متغیر کی صورت میں، ہم اسے مستقل مثال کہیں گے، لیکن مستقل کے نام کیپس میں لکھے جاتے ہیں، اور الفاظ کے درمیان (اگر ان میں سے کئی ہیں) ایک انڈر سکور ہوتا ہے - "CONSTANT_EXAMPLE"۔ مستقل کی ضرورت کیوں ہے؟ مثال کے طور پر، اگر آپ کسی پروگرام میں مسلسل کچھ مستقل قدر استعمال کرتے ہیں تو وہ کام آئیں گے۔ ہم کہتے ہیں کہ آپ نے تاریخ میں نیچے جانے اور اکیلے "The Witcher 4" گیم لکھنے کا فیصلہ کیا ہے۔ گیم واضح طور پر مرکزی کردار کے نام کا استعمال کرے گا - "جیرالٹ آف ریویا"۔ اس لائن اور دوسرے ہیروز کے ناموں کو ایک مستقل میں الگ کرنا بہتر ہے: آپ کو جس قدر کی ضرورت ہے اسے ایک جگہ پر محفوظ کیا جائے گا، اور آپ یقینی طور پر اسے دسویں مرتبہ ٹائپ کرتے وقت غلطی نہیں کریں گے۔
public class TheWitcher4 {

   private static final String GERALT_NAME = "Геральт из Ривии";
   private static final String YENNEFER_NAME = "Йеннифэр из Венгерберга";
   private static final String TRISS_NAME = "Трисс Меригольд";

   public static void main(String[] args) {

       System.out.println("Ведьмак 4");
       System.out.println("Это уже четвертая часть Ведьмака, а " + GERALT_NAME + " ниHow не определится кто ему" +
               " нравится больше: " + YENNEFER_NAME + " or " + TRISS_NAME);

       System.out.println("Но если вы никогда не играли в Ведьмака - начнем сначала.");
       System.out.println("Главного героя зовут " + GERALT_NAME);
       System.out.println(GERALT_NAME + " - ведьмак, охотник на чудовищ");
   }
}
نتیجہ:
Ведьмак 4
Это уже четвертая часть Ведьмака, а Геральт из Ривии ниHow не определится, кто ему нравится больше: Йеннифэр из Венгерберга or Трисс Меригольд.
Но если вы никогда не играли в Ведьмака — начнем сначала.
Главного героя зовут Геральт из Ривии
Геральт из Ривии — ведьмак, охотник на чудовищ
ہم نے حروف کے ناموں کو مستقل میں الگ کر دیا ہے، اور اب ہم یقینی طور پر ان کی غلط املا نہیں کریں گے، اور ہر بار انہیں ہاتھ سے لکھنے کی ضرورت نہیں ہوگی۔ ایک اور پلس: اگر ہمیں آخر کار پورے پروگرام میں کسی متغیر کی قدر کو تبدیل کرنے کی ضرورت ہے، تو اسے پورے کوڈ میں دستی طور پر دوبارہ کرنے کے بجائے ایک جگہ پر کرنا کافی ہے :)

ناقابل تغیر اقسام

جاوا میں کام کرنے کے دوران، آپ شاید پہلے ہی اس حقیقت کے عادی ہیں کہ پروگرامر تقریباً تمام اشیاء کی حالت کو مکمل طور پر کنٹرول کرتا ہے۔ مطلوب - ایک آبجیکٹ بنایا Cat۔ میں نے چاہا تو نام بدل دیا۔ اس نے چاہا تو اپنی عمر بدل دی، یا کچھ اور۔ لیکن جاوا میں ڈیٹا کی کئی اقسام ہیں جن کی ایک خاص حالت ہے۔ وہ ناقابل تغیر یا ناقابل تغیر ہیں ۔ اس کا مطلب یہ ہے کہ اگر کوئی طبقہ ناقابل تغیر ہے تو اس کی اشیاء کی حالت کو تبدیل نہیں کیا جا سکتا۔ مثالیں؟ آپ حیران ہوں گے، لیکن Immutable کلاس کی سب سے مشہور مثال ہے String! ایسا لگتا ہے کہ ہم تار کی قدر کو تبدیل نہیں کرسکتے ہیں؟ کوشش کرتے ہیں:
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

   str1 = "I love Python";//но поведение str1 ниHow не влияет на str2
   System.out.println(str2);//str2 продолжает указывать на строку "I love Java", хотя str1 уже указывает на другой an object
}
نتیجہ: میں جاوا سے محبت کرتا ہوں میں جاوا سے محبت کرتا ہوں جب ہم نے لکھا:
str1 = "I love Python";
"میں جاوا سے پیار کرتا ہوں" اسٹرنگ والی آبجیکٹ تبدیل نہیں ہوئی ہے اور کہیں نہیں گئی ہے۔ یہ محفوظ طریقے سے موجود ہے اور اس کے اندر بالکل وہی متن ہے جو پہلے تھا۔ کوڈ:
str1 = "I love Python";
ابھی ایک اور آبجیکٹ بنایا اور اب متغیر str1اس کی طرف اشارہ کرتا ہے۔ لیکن ہم کسی بھی طرح سے "میں جاوا سے محبت کرتا ہوں" آبجیکٹ کو متاثر نہیں کر سکتے۔ ٹھیک ہے، آئیے اسے مختلف طریقے سے آزمائیں! کلاس Stringطریقوں سے بھری ہوئی ہے، اور ان میں سے کچھ قطار کی حالت کو بدلتے نظر آتے ہیں! مثال کے طور پر، ایک طریقہ ہے replace(). آئیے اپنی لائن میں لفظ "جاوا" کو لفظ "Python" میں تبدیل کرتے ہیں!
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

   str1.replace("Java", "Python");//попробуем изменить состояние str1, заменив слово "Java" на “Python”
   System.out.println(str2);
}
نتیجہ: میں جاوا سے محبت کرتا ہوں میں جاوا سے محبت کرتا ہوں یہ دوبارہ کام نہیں ہوا! شاید وکر کا طریقہ کام نہیں کرتا ہے؟ آئیے ایک اور کوشش کریں۔ مثال کے طور پر، substring(). منتقل کردہ حروف کی تعداد کی بنیاد پر سٹرنگ کو تراشتا ہے۔ آئیے اپنے پہلے 10 حروف کو تراشتے ہیں:
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

   str1.substring(10);//обрезаем исходную строку
   System.out.println(str2);
}
نتیجہ: مجھے جاوا پسند ہے مجھے جاوا پسند ہے جاوا میں ناقابل تغیر: حتمی، مستقل اور ناقابل تغیر - 3 کچھ بھی نہیں بدلا ہے۔ اور یہ نہیں ہونا چاہئے. جیسا کہ ہم نے کہا، اشیاء Stringناقابل تغیر ہیں۔ پھر یہ تمام طبقاتی طریقے کیا ہیں String؟ وہ لائن کو تراش سکتے ہیں، اس میں حروف کو تبدیل کر سکتے ہیں، وغیرہ۔ اگر کچھ نہیں ہوتا تو پھر ان کی ضرورت کیوں؟ وہ کر سکتے ہیں! لیکن وہ ہر بار ایک نئی سٹرنگ آبجیکٹ واپس کرتے ہیں۔ لکھنے کا کوئی فائدہ نہیں:
str1.replace("Java", "Python");
- آپ اصل چیز کو تبدیل نہیں کریں گے۔ لیکن اگر آپ طریقہ کا نتیجہ ایک نئے حوالہ متغیر میں لکھتے ہیں، تو آپ کو فوری طور پر فرق نظر آئے گا!
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

   String str1AfterReplacement =  str1.replace("Java", "Python");
   System.out.println(str2);

   System.out.println(str1AfterReplacement);
}
یہ تمام طریقے کام کرنے کا واحد طریقہ ہے String۔ آپ "I love Java" آبجیکٹ کے ساتھ کچھ نہیں کر سکتے ۔ بس ایک نیا آبجیکٹ بنائیں اور لکھیں: "نیا آبجیکٹ = "مجھے جاوا پسند ہے" آبجیکٹ کے ساتھ کچھ ہیرا پھیری کا نتیجہ ۔ کون سی دوسری قسمیں ناقابل تغیر ہیں؟ جس چیز سے آپ کو یقینی طور پر اب یاد رکھنے کی ضرورت ہے - قدیم اقسام سے زیادہ ریپر کی تمام کلاسیں ناقابل تغیر ہیں۔ Integer, Byte, Character, Short, Boolean, Long, Double, Float- یہ تمام کلاسیں ناقابل تغیر اشیاء تخلیق کرتی ہیں۔ اس میں بڑی تعداد بنانے کے لیے استعمال ہونے والی کلاسیں بھی شامل ہیں - BigIntegerاور BigDecimal. ہم نے حال ہی میں مستثنیات سے گزرے اور اس کو چھوا StackTrace۔ تو: java.lang.StackTraceElement کلاس کی اشیاء بھی ناقابل تغیر ہیں۔ یہ منطقی ہے: اگر کوئی ہمارے اسٹیک پر ڈیٹا کو تبدیل کر سکتا ہے، تو یہ اس کے ساتھ تمام کاموں کی نفی کر سکتا ہے۔ تصور کریں کہ کوئی StackTrace میں جاتا ہے اور OutOfMemoryError کو FileNotFoundException میں تبدیل کرتا ہے ۔ اور آپ کو اس اسٹیک کے ساتھ کام کرنا چاہئے اور خرابی کی وجہ تلاش کرنا چاہئے۔ اور پروگرام فائلوں کو بالکل بھی استعمال نہیں کرتا ہے :) لہذا، محفوظ پہلو پر رہنے کے لیے، ان اشیاء کو ناقابل تغیر بنا دیا گیا تھا۔ ٹھیک ہے، StackTraceElement کے ساتھ یہ کم و بیش واضح ہے۔ کوئی کیوں تاروں کو ناقابل تغیر بنانا چاہے گا؟ اگر ان کی اقدار کو تبدیل کرنا ممکن ہو تو کیا مسئلہ ہو گا۔ یہ شاید اور بھی آسان ہوگا :/ اس کی کئی وجوہات ہیں۔ سب سے پہلے، میموری کو بچانا۔ غیر تبدیل شدہ تاروں کو رکھا جا سکتا ہے String Poolاور ہر بار نئے بنانے کے بجائے وہی استعمال کیے جا سکتے ہیں۔ دوسرا، حفاظت. مثال کے طور پر، کسی بھی پروگرام میں زیادہ تر لاگ ان اور پاس ورڈ تار ہوتے ہیں۔ ان کو تبدیل کرنے کا امکان اجازت کے ساتھ مسائل کا باعث بن سکتا ہے۔ اور بھی وجوہات ہیں، لیکن ہم نے ابھی تک جاوا سیکھنے میں ان تک رسائی حاصل نہیں کی ہے- ہم بعد میں واپس آئیں گے۔
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION