JavaRush /جاوا بلاگ /Random-UR /جاوا 8 میں پہلے سے طے شدہ طریقے: وہ کیا کر سکتے ہیں اور ک...
Spitfire
سطح

جاوا 8 میں پہلے سے طے شدہ طریقے: وہ کیا کر سکتے ہیں اور کیا نہیں کر سکتے؟

گروپ میں شائع ہوا۔
اپریل 2014 کو پیٹر ورہاس کے لکھے ہوئے مضمون کا ترجمہ ۔ جاوا 8 میں پہلے سے طے شدہ طریقے: وہ کیا کر سکتے ہیں اور کیا نہیں کر سکتے؟  - 1مترجم کی طرف سے: اصطلاح " پہلے سے طے شدہ طریقہ " ابھی ابھی جاوا میں نمودار ہوئی ہے اور مجھے یقین نہیں ہے کہ آیا اس کا روسی زبان میں کوئی ترجمہ موجود ہے۔ میں "پہلے سے طے شدہ طریقہ" کی اصطلاح استعمال کروں گا، حالانکہ مجھے نہیں لگتا کہ یہ مثالی ہے۔ میں آپ کو مزید کامیاب ترجمے پر بات کرنے کی دعوت دیتا ہوں۔

پہلے سے طے شدہ طریقہ کیا ہے؟

اب، جاوا 8 کے اجراء کے ساتھ، آپ انٹرفیس میں نئے طریقے شامل کر سکتے ہیں تاکہ انٹرفیس ان کلاسوں کے ساتھ مطابقت رکھتا ہو جو اسے نافذ کرتی ہیں۔ یہ بہت اہم ہے اگر آپ ایک لائبریری تیار کر رہے ہیں جو کیو سے نیویارک تک بہت سے پروگرامرز استعمال کرتے ہیں۔ جاوا 8 سے پہلے، اگر آپ کسی لائبریری میں انٹرفیس کی تعریف کرتے ہیں، تو آپ اس میں طریقے شامل نہیں کر سکتے تھے اس خطرے کے بغیر کہ آپ کے انٹرفیس کو چلانے والی کچھ ایپلیکیشن اپ ڈیٹ ہونے پر ٹوٹ جائے گی۔ تو، جاوا 8 میں آپ اب اس سے ڈر نہیں سکتے؟ نہیں تم نہیں کر سکتے. انٹرفیس میں پہلے سے طے شدہ طریقہ شامل کرنا کچھ کلاسوں کو ناقابل استعمال بنا سکتا ہے۔ آئیے پہلے طے شدہ طریقوں کے بارے میں اچھی چیزوں کو دیکھیں۔ جاوا 8 میں، طریقہ کو براہ راست انٹرفیس میں لاگو کیا جا سکتا ہے۔ (ایک انٹرفیس میں جامد طریقوں کو بھی لاگو کیا جا سکتا ہے، لیکن یہ ایک اور کہانی ہے۔) ایک انٹرفیس میں لاگو کردہ طریقہ کو ڈیفالٹ میتھڈ کہا جاتا ہے، اور اسے ڈیفالٹ کلیدی لفظ سے ظاہر کیا جاتا ہے ۔ اگر ایک کلاس انٹرفیس کو لاگو کرتی ہے، تو یہ انٹرفیس میں لاگو کیے گئے طریقوں کو لاگو کر سکتا ہے، لیکن اس کی ضرورت نہیں ہے۔ کلاس کو پہلے سے طے شدہ نفاذ کی وراثت ملتی ہے۔ یہی وجہ ہے کہ جب ان کے نافذ کردہ انٹرفیس کو تبدیل کرتے وقت کلاسوں میں ترمیم کرنا ضروری نہیں ہے۔

ایک سے زیادہ وراثت؟

چیزیں مزید پیچیدہ ہو جاتی ہیں اگر کوئی کلاس ایک سے زیادہ (کہیں، دو) انٹرفیس کو لاگو کرتی ہے، اور وہ ایک ہی طے شدہ طریقہ کو نافذ کرتی ہے۔ کلاس کو کون سا طریقہ وراثت میں ملے گا؟ جواب کوئی نہیں ہے۔ اس صورت میں، کلاس کو خود طریقہ کار کو نافذ کرنا ہوگا (یا تو براہ راست یا کسی اور کلاس سے وراثت میں لے کر)۔ صورت حال ایسی ہی ہے اگر صرف ایک انٹرفیس میں ڈیفالٹ طریقہ ہو، اور دوسرے میں وہی طریقہ خلاصہ ہو۔ Java 8 نظم و ضبط رکھنے اور مبہم حالات سے بچنے کی کوشش کرتا ہے۔ اگر ایک سے زیادہ انٹرفیس میں طریقوں کا اعلان کیا جاتا ہے، تو کلاس کے ذریعہ کوئی ڈیفالٹ نفاذ وراثت میں نہیں ملتا ہے - آپ کو ایک تالیف کی خرابی ملے گی۔ اگرچہ، اگر آپ کی کلاس پہلے ہی مرتب ہو چکی ہے تو آپ کو تالیف کی غلطی نہیں ہو سکتی۔ جاوا 8 اس سلسلے میں کافی مضبوط نہیں ہے۔ اس کی وجوہات ہیں، جن پر میں بحث نہیں کرنا چاہتا (مثال کے طور پر: جاوا ریلیز پہلے ہی جاری ہو چکی ہے اور بات چیت کا وقت بہت گزر چکا ہے اور عام طور پر، یہ ان کے لیے جگہ نہیں ہے)۔
  • فرض کریں کہ آپ کے پاس دو انٹرفیس ہیں اور ایک کلاس ان دونوں کو لاگو کرتی ہے۔
  • انٹرفیس میں سے ایک پہلے سے طے شدہ طریقہ m() کو نافذ کرتا ہے۔
  • آپ تمام انٹرفیس اور کلاس کو مرتب کرتے ہیں۔
  • آپ ایک ایسے انٹرفیس کو تبدیل کرتے ہیں جس میں m() طریقہ نہیں ہے اسے تجریدی طریقہ قرار دے کر۔
  • آپ صرف ترمیم شدہ انٹرفیس مرتب کرتے ہیں۔
  • کلاس شروع کریں۔
جاوا 8 میں پہلے سے طے شدہ طریقے: وہ کیا کر سکتے ہیں اور کیا نہیں کر سکتے؟  - 2اس معاملے میں کلاس کام کرتی ہے۔ آپ اسے اپ ڈیٹ شدہ انٹرفیس کے ساتھ مرتب نہیں کر سکتے، لیکن یہ پرانے ورژن کے ساتھ مرتب کیا گیا تھا اور اس لیے کام کرتا ہے۔ ابھی
  • خلاصہ m() طریقہ کے ساتھ انٹرفیس کو تبدیل کریں اور پہلے سے طے شدہ نفاذ شامل کریں۔
  • ترمیم شدہ انٹرفیس کو مرتب کریں۔
  • کلاس چلائیں: غلطی۔
جب دو انٹرفیس ہوتے ہیں جو کسی طریقہ کا پہلے سے طے شدہ نفاذ فراہم کرتے ہیں، تو اس طریقہ کو کلاس میں نہیں بلایا جا سکتا جب تک کہ اسے خود کلاس کے ذریعے لاگو نہ کیا جائے (دوبارہ، یا تو خود یا کسی اور کلاس سے وراثت میں)۔ جاوا 8 میں پہلے سے طے شدہ طریقے: وہ کیا کر سکتے ہیں اور کیا نہیں کر سکتے؟  - 3کلاس کے موافق۔ یہ ایک ترمیم شدہ انٹرفیس کے ساتھ لوڈ کیا جا سکتا ہے. یہ اس وقت تک چل سکتا ہے جب تک کہ کوئی طریقہ نہ کہا جائے جس کا دونوں انٹرفیس میں پہلے سے طے شدہ نفاذ ہو۔

مثال کوڈ

جاوا 8 میں پہلے سے طے شدہ طریقے: وہ کیا کر سکتے ہیں اور کیا نہیں کر سکتے؟  - 4مندرجہ بالا کو ظاہر کرنے کے لیے، میں نے C.java کلاس کے لیے ایک ٹیسٹ ڈائرکٹری اور I1.java اور I2.java فائلوں میں انٹرفیس کے لیے 3 ذیلی ڈائریکٹریز بنائی ہیں۔ ٹیسٹ کے لیے روٹ ڈائرکٹری C.java کلاس کے لیے سورس کوڈ پر مشتمل ہے۔ بیس ڈائرکٹری انٹرفیس کا ایک ورژن پر مشتمل ہے جو عمل درآمد اور تالیف کے لیے موزوں ہے: انٹرفیس I1 کا ایک طے شدہ طریقہ ہے m(); I2 انٹرفیس میں ابھی تک کوئی طریقہ نہیں ہے۔ کلاس کا ایک طریقہ ہے mainلہذا ہم اسے جانچنے کے لیے اس پر عمل کر سکتے ہیں۔ یہ چیک کرتا ہے کہ آیا کوئی کمانڈ لائن دلائل موجود ہیں، لہذا ہم اسے آسانی سے یا تو کال کے ساتھ یا اس کے بغیر چلا سکتے ہیں m()۔
~/github/test$ cat C.java
public class C implements I1, I2 {
  public static void main(String[] args) {
    C c = new C();
    if( args.length == 0 ){
      c.m();
    }
  }
}
~/github/test$ cat base/I1.java
public interface I1 {
  default void m(){
    System.out.println("hello interface 1");
  }
}
~/github/test$ cat base/I2.java
public interface I2 {
}
آپ کمانڈ لائن سے کلاس کو مرتب اور چلا سکتے ہیں۔
~/github/test$ javac -cp .:base C.java
~/github/test$ java -cp .:base C
hello interface 1
مطابقت پذیر ڈائرکٹری میں I2 انٹرفیس کا ایک ورژن شامل ہے جو m() طریقہ کو خلاصہ قرار دیتا ہے، اور تکنیکی وجوہات کی بناء پر، I1.java کی ایک غیر ترمیم شدہ کاپی۔
~/github/test$ cat compatible/I2.java

public interface I2 {
  void m();
}
اس طرح کا سیٹ C کلاس کو مرتب کرنے کے لیے استعمال نہیں کیا جا سکتا:
~/github/test$ javac -cp .:compatible C.java
C.java:1: error: C is not abstract and does not override abstract method m() in I2
public class C implements I1, I2 {
       ^
1 error
غلطی کا پیغام بہت درست ہے۔ تاہم، ہمارے پاس پچھلی تالیف سے C.class ہے اور، اگر ہم انٹرفیس کو ہم آہنگ ڈائریکٹری میں مرتب کرتے ہیں، تو ہمارے پاس دو انٹرفیس ہوں گے جو اب بھی کلاس چلانے کے لیے استعمال کیے جاسکتے ہیں:
~/github/test$ javac compatible/I*.java
~/github/test$ java -cp .:compatible C
hello interface 1
تیسری ڈائرکٹری - wrong- ورژن I2 پر مشتمل ہے، جو طریقہ کا بھی اعلان کرتی ہے m():
~/github/test$ cat wrong/I2.java
public interface I2 {
  default void m(){
    System.out.println("hello interface 2");
  }
}
آپ کو تالیف کے بارے میں بھی فکر کرنے کی ضرورت نہیں ہے۔ اگرچہ طریقہ دو بار اعلان کیا گیا ہے، کلاس اب بھی استعمال کیا جا سکتا ہے اور چلایا جا سکتا ہے جب تک کہ m() طریقہ نہیں کہا جاتا ہے. یہ وہی ہے جس کے لئے ہمیں کمانڈ لائن دلیل کی ضرورت ہے:
~/github/test$ javac wrong/*.java
~/github/test$ java -cp .:wrong C
Exception in thread "main" java.lang.IncompatibleClassChangeError: Conflicting default methods: I1.m I2.m
    at C.m(C.java)
    at C.main(C.java:5)
~/github/test$ java -cp .:wrong C x
~/github/test$

نتیجہ

جب آپ اپنی لائبریری کو جاوا 8 میں پورٹ کرتے ہیں اور اپنے انٹرفیس کو ڈیفالٹ طریقے شامل کرنے کے لیے تبدیل کرتے ہیں، تو شاید آپ کو کوئی پریشانی نہیں ہوگی۔ کم از کم، جاوا 8 لائبریری کے ڈویلپرز اس کی امید کر رہے ہیں کیونکہ وہ فعالیت میں اضافہ کرتے ہیں۔ آپ کی لائبریری کا استعمال کرنے والی ایپلیکیشنز ابھی بھی اسے Java 7 کے لیے استعمال کر رہی ہیں، جہاں پہلے سے طے شدہ طریقے نہیں ہیں۔ اگر کئی لائبریریوں کو ایک ساتھ استعمال کیا جائے تو تصادم کا امکان ہے۔ اس سے کیسے بچا جائے؟ اپنی لائبریری کے API کو پہلے کی طرح ڈیزائن کریں۔ پہلے سے طے شدہ طریقوں کی صلاحیتوں پر بھروسہ کرکے مطمئن نہ ہوں۔ وہ ایک آخری سہارا ہیں۔ دوسرے انٹرفیس کے ساتھ تصادم سے بچنے کے لیے احتیاط سے ناموں کا انتخاب کریں۔ آئیے دیکھتے ہیں کہ اس فیچر کا استعمال کرتے ہوئے جاوا کے لیے کس طرح ترقی ہوگی۔
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION